home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / net / sun3.md / netUltra.c < prev   
C/C++ Source or Header  |  1990-11-09  |  91KB  |  3,082 lines

  1. /* 
  2.  * netUltra.c --
  3.  *
  4.  *    Routines for handling the Ultranet VME Adapter card..
  5.  *
  6.  * Copyright 1990 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /sprite/src/kernel/net/sun3.md/RCS/netUltra.c,v 1.4 90/11/09 12:03:58 jhh Exp $ SPRITE (Berkeley)";
  18. #endif /* not lint */
  19.  
  20. #include <sprite.h>
  21. #include <vm.h>
  22. #include <vmMach.h>
  23. #include <mach.h>
  24. #include <netUltraInt.h>
  25. #include <dev/ultra.h>
  26. #include <fmt.h>
  27. #include <sync.h>
  28. #include <dbg.h>
  29. #include <rpcPacket.h>
  30. #include <assert.h>
  31.  
  32. /*
  33.  * "Borrow" the Vax format for the format of the Ultranet adapter (it
  34.  * is really a 386.  We need to swap some of the words in the
  35.  * diagnostic and information structures.
  36.  */
  37.  
  38. #define NET_ULTRA_FORMAT FMT_VAX_FORMAT
  39.  
  40. Boolean        netUltraDebug = FALSE;
  41. Boolean        netUltraTrace = TRUE;
  42. int        netUltraMapThreshold = NET_ULTRA_MAP_THRESHOLD;
  43. static int    packetsSunk = 0;
  44. static Time    sinkStartTime;
  45. static Time    sinkEndTime;
  46.  
  47. #define MIN(a,b) ((a) < (b) ? (a) : (b))
  48.  
  49. #define WAIT_FOR_REPLY(ptr, count) {        \
  50.     int    i;                    \
  51.     for(i = (count); i > 0; i -= 100) {        \
  52.     MACH_DELAY(100);            \
  53.     if (*((volatile int *)ptr) != 0) {    \
  54.         break;                \
  55.     }                    \
  56.     }                        \
  57. }
  58.  
  59. /*
  60.  * The following are the names of the diagnostic tests as listed in the
  61.  * uvm man page provided in the Ultranet documentation.
  62.  */
  63. static char    *diagNames[] = {
  64.     "EPROM checksum",
  65.     "Abbreviated RAM check",
  66.     "Interrupt controller and interval timer",
  67.     "Internal loopback",
  68.     "FIFO RAM check",
  69.     "Checksum gate arrays",
  70.     "NMI control logic"
  71. };
  72. /*
  73.  * The following are the names of the extended diagnostic tests as
  74.  * listed in the uvm man page.
  75.  */
  76. static char    *extDiagNames[] = {
  77.     "EPROM checksum",
  78.     "Full RAM check",
  79.     "Interrupt controller and interval timer",
  80.     "Internal or external loopback",
  81.     "FIFO RAM check",
  82.     "Checksum gate arrays",
  83.     "NMI control logic",
  84.     "DMA to hosts memory using VME bus",
  85.     "Extended FIFO RAM check",
  86.     "FIFO Control logic"
  87. };
  88.  
  89. /*
  90.  * This is a "wildcard" address that matches any TL address.
  91.  * Once again we have to lie about the size of a Net_Address
  92.  * since the adapter will puke if it isn't 7 bytes (why have it
  93.  * if you can't change it?).
  94.  */
  95. static Net_UltraTLAddress    wildcardAddress = 
  96.                 {7, NET_ULTRA_TSAP_SIZE};
  97.  
  98. /*
  99.  * Forward declarations.
  100.  */
  101.  
  102. static Sync_Condition    dsndTestDone;
  103. static int        dsndCount;
  104.  
  105. static char         *GetStatusString _ARGS_ ((int status));
  106. static void        InitQueues _ARGS_((NetUltraState *statePtr));
  107. static void        StandardDone _ARGS_((Net_Interface *interPtr, 
  108.                 NetUltraXRBInfo *infoPtr));
  109. static void        ReadDone _ARGS_((Net_Interface *interPtr, 
  110.                 NetUltraXRBInfo *infoPtr));
  111. static void        EchoDone _ARGS_((Net_Interface *interPtr, 
  112.                 NetUltraXRBInfo *infoPtr));
  113. static ReturnStatus    NetUltraSendDgram _ARGS_((Net_Interface *interPtr,
  114.                 Net_Address *netAddressPtr, int count,
  115.                 int bufSize, Address buffer, Time *timePtr));
  116. static void        DgramSendDone _ARGS_((Net_Interface *interPtr, 
  117.                 NetUltraXRBInfo *infoPtr));
  118. static void        OutputDone _ARGS_((Net_Interface *interPtr, 
  119.                 NetUltraXRBInfo *infoPtr));
  120. static void        SourceDone _ARGS_((Net_Interface *interPtr, 
  121.                 NetUltraXRBInfo *infoPtr));
  122. static ReturnStatus    NetUltraSource _ARGS_((Net_Interface *interPtr,
  123.                 Net_Address *netAddressPtr, int count,
  124.                 int bufSize, Address buffer, Time *timePtr));
  125. static void        NetUltraResetCallback _ARGS_((ClientData data,
  126.                 Proc_CallInfo *infoPtr));
  127.  
  128. /*
  129.  * Macros for mapping between kernel, DVMA and VME addresses.
  130.  */
  131.  
  132. #define    DVMA_TO_BUFFER(addr, statePtr)         \
  133.     ((Address) (((((unsigned int) (addr)) -     \
  134.     ((unsigned int) (statePtr)->buffersDVMA)) + \
  135.     ((int) (statePtr)->buffers))))
  136.  
  137. #define BUFFER_TO_DVMA(addr, statePtr)         \
  138.     ((Address) ((((unsigned int) (addr)) -     \
  139.     ((unsigned int) (statePtr)->buffers)) +     \
  140.     ((unsigned int) (statePtr)->buffersDVMA)))
  141.  
  142. #define DVMA_TO_VME(addr, statePtr)         \
  143.     ((Address) (((unsigned int) (addr)) -     \
  144.     ((unsigned int) VMMACH_DMA_START_ADDR)))
  145.  
  146. #define VME_TO_DVMA(addr, statePtr)         \
  147.     ((Address) (((unsigned int) (addr)) +     \
  148.     ((unsigned int) VMMACH_DMA_START_ADDR)))
  149.  
  150. #define BUFFER_TO_VME(addr, statePtr) \
  151.     ((Address) (DVMA_TO_VME(BUFFER_TO_DVMA(addr,statePtr), (statePtr))))
  152.  
  153. #define VME_TO_BUFFER(addr, statePtr) \
  154.     ((Address) (DVMA_TO_BUFFER(VME_TO_DVMA((addr),statePtr),(statePtr))))
  155.  
  156. #define DVMA_ADDRESS(addr, statePtr) \
  157.     ((unsigned int) (addr) < ((unsigned int)VMMACH_DMA_START_ADDR)? FALSE :TRUE)
  158.  
  159.  
  160.  
  161. /*
  162.  *----------------------------------------------------------------------
  163.  *
  164.  * NetUltraInit --
  165.  *
  166.  *    Initialize the Ultranet VME adapter card.
  167.  *
  168.  * Results:
  169.  *    SUCCESS if the Ultranet card was found and initialized.
  170.  *    FAILURE otherwise.
  171.  *
  172.  * Side effects:
  173.  *    None.
  174.  *
  175.  *----------------------------------------------------------------------
  176.  */
  177.  
  178. ReturnStatus
  179. NetUltraInit(interPtr)
  180.     Net_Interface    *interPtr;     /* Network interface. */
  181. {
  182.     unsigned int        ctrlAddr;
  183.     NetUltraState        *statePtr;
  184.     ReturnStatus        status = SUCCESS;
  185.     int                zero = 0;
  186.     NetUltraExtDiagCommand     extDiagCmd;
  187.     NetUltraInfoCommand        infoCmd;
  188.     char            *buffer;
  189.  
  190.     /*
  191.      * Make sure that we agree with the adapter as to the size of the 
  192.      * command blocks and other structures.
  193.      */
  194.     assert(sizeof(Net_UltraAddress) == 8);
  195.     assert(sizeof(Net_UltraTLAddress) == 16);
  196.     assert(sizeof(Net_UltraHeader) == 56);
  197.     assert(sizeof(NetUltraDMAInfo) == 16);
  198.     assert(sizeof(NetUltraRequestHdr) == 16);
  199.     assert(sizeof(NetUltraDatagramRequest) == 56);
  200.     assert(sizeof(NetUltraStartRequest) == 112);
  201.     assert(sizeof(NetUltraStopRequest) == 16);
  202.     assert(sizeof(NetUltraRequest) == 112);
  203.     assert(sizeof(NetUltraXRB) == 132);
  204.     assert(sizeof(NetUltraInitCommand) == 64);
  205.     assert(sizeof(NetUltraDiagCommand) == 36);
  206.     assert(sizeof(NetUltraExtDiagCommand) == 24);
  207.     assert(sizeof(NetUltraLoadCommand) == 24);
  208.     assert(sizeof(NetUltraGoCommand) == 12);
  209.     assert(sizeof(Net_UltraHeader) == sizeof(NetUltraDatagramRequest));
  210.  
  211.     ctrlAddr = (unsigned int) interPtr->ctrlAddr;
  212.     /*
  213.      * If the address is physical (not in kernel's virtual address space)
  214.      * then we have to map it in.
  215.      */
  216.     if (interPtr->virtual == FALSE) {
  217.     ctrlAddr = (unsigned int) VmMach_MapInDevice((Address) ctrlAddr, 3);
  218.     }
  219.     statePtr = (NetUltraState *) malloc (sizeof(NetUltraState));
  220.     bzero((char *) statePtr, sizeof(NetUltraState));
  221.     /*
  222.      * The first register is the interrupt register, then
  223.      * the reset register, separated by 12 bytes.
  224.      */
  225.     statePtr->intrReg = (int *) ctrlAddr;
  226.     statePtr->resetReg = (int *) (ctrlAddr + 0x10);
  227.     /*
  228.      * Now poke the reset register.
  229.      */
  230.     status = Mach_Probe(sizeof(int), (char *) &zero,
  231.         (char *) statePtr->resetReg);
  232.     if (status != SUCCESS) {
  233.     /* 
  234.      * Got a bus error.
  235.      */
  236.     goto exit;
  237.     }
  238.     if (netUltraDebug) {
  239.     printf("NetUltraInit: adapter at 0x%x probed successfully\n",
  240.         statePtr->intrReg);
  241.     }
  242.     MACH_DELAY(NET_ULTRA_RESET_DELAY);
  243.     statePtr->magic = NET_ULTRA_STATE_MAGIC;
  244.     statePtr->flags = NET_ULTRA_STATE_EXIST | NET_ULTRA_STATE_EPROM |
  245.             NET_ULTRA_STATE_NORMAL;
  246.     statePtr->interPtr = interPtr;
  247.     interPtr->interfaceData = (ClientData) statePtr;
  248.     statePtr->tracePtr = statePtr->traceBuffer;
  249.     statePtr->traceSequence = 0;
  250.     /*
  251.      * Get the adapter information.
  252.      */
  253.     status = NetUltraInfo(statePtr, &infoCmd);
  254.     if (status == SUCCESS) {
  255.     printf(
  256.     "UltraNet adapter %d.%d, Revision %d, Option %d, Firmware %d, Serial %d\n",
  257.         infoCmd.hwModel, infoCmd.hwVersion, 
  258.         infoCmd.hwRevision, infoCmd.hwOption,
  259.         infoCmd.version, infoCmd.hwSerial);
  260.     if (infoCmd.error == 0) {
  261.         printf("Ultranet adapter passed all diagnostics.\n");
  262.     } else {
  263.         int    tmp = infoCmd.error;
  264.         int i;
  265.         printf(
  266.         "Ultranet adapter failed diagnostics (0x%x).\n", tmp);
  267.         printf("The following tests failed:\n");
  268.         for (i = 0; i < sizeof(int) * 8; i++) {
  269.         if (tmp & 1) {
  270.             printf("%2d: %s\n", i+1, diagNames[i]);
  271.         }
  272.         tmp >>= 1;
  273.         }
  274.         status = FAILURE;
  275.         goto exit;
  276.     }
  277.     } else {
  278.     printf("NetUltraInit: unable to send info command to adapter\n");
  279.     goto exit;
  280.     }
  281.     /*
  282.      * Send an extended diagnostics command to the adapter.
  283.      */
  284.     buffer = (char *) malloc(NET_ULTRA_EXT_DIAG_BUF_SIZE);
  285.     status = NetUltraExtDiag(statePtr, FALSE, buffer, &extDiagCmd);
  286.     free(buffer);
  287.     if (status == SUCCESS) {
  288.     if (extDiagCmd.error == 0) {
  289.         printf("Ultranet adapter passed all extended diagnostics.\n");
  290.     } else {
  291.         int    tmp = extDiagCmd.error;
  292.         int i;
  293.         printf(
  294.         "Ultranet adapter failed extended diagnostics (0x%x).\n", tmp);
  295.         printf("The following tests failed:\n");
  296.         for (i = 0; i < sizeof(int) * 8; i++) {
  297.         if (tmp & 1) {
  298.             printf("%2d: %s\n", i+1, extDiagNames[i]);
  299.         }
  300.         tmp >>= 1;
  301.         }
  302.         status = FAILURE;
  303.         goto exit;
  304.     } 
  305.     } else {
  306.     printf(
  307.     "NetUltraInit: unable to send extended diagnostics command to adapter\n");
  308.     goto exit;
  309.     }
  310.     interPtr->ctrlAddr = (Address) ctrlAddr;
  311.     statePtr->queuesInit = FALSE;
  312.     InitQueues(statePtr);
  313.     statePtr->priority = NET_ULTRA_INTERRUPT_PRIORITY;
  314.     statePtr->requestLevel = NET_ULTRA_VME_REQUEST_LEVEL;
  315.     statePtr->addressSpace = NET_ULTRA_VME_ADDRESS_SPACE;
  316.     Mach_SetHandler(interPtr->vector, Net_Intr, (ClientData) interPtr);
  317.     interPtr->init     = NetUltraInit;
  318.     interPtr->intr    = NetUltraIntr;
  319.     interPtr->ioctl    = NetUltraIOControl;
  320.     interPtr->reset     = Net_UltraReset;
  321.     interPtr->output     = NetUltraOutput;
  322.     interPtr->netType    = NET_NETWORK_ULTRA;
  323.     interPtr->maxBytes    = NET_ULTRA_MAX_BYTES;
  324.     interPtr->minBytes    = NET_ULTRA_MIN_BYTES;
  325.     if (sizeof(NetUltraXRB) != 132) {
  326.     printf("NetUltraInit: WARNING: NetUltraXRB is not 132 bytes!!!\n");
  327.     }
  328. exit:
  329.     if (status != SUCCESS && statePtr != (NetUltraState *) NIL) {
  330.     free((char *) statePtr);
  331.     }
  332.     return status;
  333. }
  334.  
  335. /*
  336.  *----------------------------------------------------------------------
  337.  *
  338.  * NetUltraHardReset --
  339.  *
  340.  *    Does a hard reset of the Ultranet adapter. This means the adapter
  341.  *    board goes back to its state right after power-up -- no 
  342.  *    micro-code or anything.
  343.  *
  344.  * Results:
  345.  *    SUCCESS if a reply was received properly, FAILURE otherwise
  346.  *
  347.  * Side effects:
  348.  *    The ultranet adapter is initialized.
  349.  *
  350.  *----------------------------------------------------------------------
  351.  */
  352.  
  353. ReturnStatus
  354. NetUltraHardReset(interPtr)
  355.     Net_Interface    *interPtr;    /* Interface to reset. */
  356. {
  357.     NetUltraState    *statePtr;    /* State of the adapter. */
  358.     ReturnStatus    status = SUCCESS;
  359.     int            zero = 0;
  360.  
  361.     statePtr = (NetUltraState *) interPtr->interfaceData;
  362.     printf("Ultra: adapter reset.\n");
  363.     status = Mach_Probe(sizeof(int), (char *) &zero, 
  364.         (char *) statePtr->resetReg);
  365.     if (status != SUCCESS) {
  366.     /*
  367.      * Adapter is no longer responding.
  368.      */
  369.     printf("NetUltraHardReset: adapter did not respond to reset!!\n");
  370.     statePtr->flags = 0;
  371.     return FAILURE;
  372.     }
  373.     MACH_DELAY(NET_ULTRA_RESET_DELAY);
  374.     InitQueues(statePtr);
  375.     /*
  376.      * After a reset the adapter is in the EPROM mode.
  377.      * This allows several additional commands (load, go, etc.) to be
  378.      * sent to the adapter.
  379.      */
  380.     statePtr->flags = NET_ULTRA_STATE_EXIST | NET_ULTRA_STATE_EPROM;
  381.     return status;
  382. }
  383.  
  384. /*
  385.  *----------------------------------------------------------------------
  386.  *
  387.  * NetUltraInitAdapter --
  388.  *
  389.  *    Allocate the various queues and send the initialization command
  390.  *    to the adapter.
  391.  *
  392.  * Results:
  393.  *    Standard Sprite return status.
  394.  *
  395.  * Side effects:
  396.  *    The adapter board is initialized.
  397.  *
  398.  *----------------------------------------------------------------------
  399.  */
  400.  
  401. ReturnStatus
  402. NetUltraInitAdapter(statePtr)
  403.     NetUltraState    *statePtr;    /* State of the adapter. */
  404. {
  405.     ReturnStatus    status;
  406.     NetUltraInitCommand    cmd;        /* Init command block. */
  407.     Net_Interface    *interPtr;
  408.  
  409.     interPtr = statePtr->interPtr;
  410.     MASTER_LOCK(&interPtr->mutex);
  411.     if (!(statePtr->flags & NET_ULTRA_STATE_GO)) {
  412.     if (netUltraDebug) {
  413.         printf("NetUltraInitAdapter: device is not started.\n");
  414.     }
  415.     status = FAILURE;
  416.     goto exit;
  417.     }
  418.     bzero((char *) &cmd, sizeof(cmd));
  419.     cmd.opcode = NET_ULTRA_INIT_OPCODE;
  420.     cmd.toAdapterAddr = (int) DVMA_TO_VME(statePtr->firstToAdapterPtr, 
  421.                     statePtr);
  422.     cmd.toAdapterNum = statePtr->lastToAdapterPtr - 
  423.             statePtr->firstToAdapterPtr + 1;
  424.     cmd.toHostAddr = (int) DVMA_TO_VME(statePtr->firstToHostPtr, statePtr);
  425.     cmd.toHostNum = statePtr->lastToHostPtr - statePtr->firstToHostPtr + 1;
  426.     cmd.XRBSize = sizeof(NetUltraXRB);
  427.     cmd.priority = (char) statePtr->priority;
  428.     cmd.vector = (char) interPtr->vector;
  429.     cmd.requestLevel = (char) statePtr->requestLevel;
  430.     cmd.addressSpace = (char) statePtr->addressSpace;
  431.     status = NetUltraSendCmd(statePtr, NET_ULTRA_INIT_OK, sizeof(cmd), 
  432.             (Address) &cmd);
  433.     if (status != SUCCESS) {
  434.     if (cmd.reply == NET_ULTRA_BAD_SIZE) {
  435.         printf("NetUltraInitAdapter: adapter disagrees on size of XRB\n");
  436.     }
  437.     goto exit;
  438.     }
  439.     statePtr->flags &= ~NET_ULTRA_STATE_GO;
  440.     statePtr->flags |= NET_ULTRA_STATE_INIT;
  441. exit:
  442.     MASTER_UNLOCK(&interPtr->mutex);
  443.     return status;
  444.  
  445. /*
  446.  *----------------------------------------------------------------------
  447.  *
  448.  * NetUltraStart--
  449.  *
  450.  *    Send a start request to the board.
  451.  *    Assumes the interface mutex is held.
  452.  *
  453.  * Results:
  454.  *    Standard Sprite return status.
  455.  *
  456.  * Side effects:
  457.  *    A start request is sent to the board.
  458.  *
  459.  *----------------------------------------------------------------------
  460.  */
  461.  
  462. ReturnStatus
  463. NetUltraStart(statePtr)
  464.     NetUltraState    *statePtr;    /* State of the adapter. */
  465. {
  466.     NetUltraRequest        request;
  467.     NetUltraStartRequest    *startPtr;
  468.     NetUltraRequestHdr        *hdrPtr;
  469.     Net_Interface        *interPtr;
  470.     int                i;
  471.     int                power = 0;
  472.     int                tmp;
  473.     ReturnStatus        status = SUCCESS;
  474.     static int            sequence = 0;
  475.     Sync_Condition        startComplete;
  476.  
  477.     interPtr = statePtr->interPtr;
  478.     startPtr = &request.start;
  479.     hdrPtr = &startPtr->hdr;
  480.     if (!(NET_ADDRESS_COMPARE(interPtr->netAddress[NET_PROTO_RAW],
  481.         netZeroAddress))){
  482.     printf(
  483. "NetUltraStart: can't send start command - adapter address not set\n");
  484.     status = FAILURE;
  485.     goto exit;
  486.     }
  487.     if (statePtr->flags & NET_ULTRA_STATE_START) {
  488.     printf("NetUltraStart: adapter already started.\n");
  489.     status = FAILURE;
  490.     goto exit;
  491.     }
  492.     if (!(statePtr->flags & NET_ULTRA_STATE_INIT)) {
  493.     printf("NetUltraStart: adapter not initialized.\n");
  494.     status = FAILURE;
  495.     goto exit;
  496.     }
  497.     bzero((char *) &request, sizeof(request));
  498.     hdrPtr->cmd = NET_ULTRA_NEW_START_REQ;
  499.     startPtr->sequence = sequence;
  500.     sequence++;
  501.     startPtr->hostType = NET_ULTRA_START_HOSTTYPE_SUN;
  502.     /*
  503.      * Determine which power of 2 equals the maximum packet size. 
  504.      */
  505.     tmp = interPtr->maxBytes;
  506.     for (i = 0; i < sizeof(int) * 8; i++) {
  507.     if (tmp & 1) {
  508.         power = i;
  509.     }
  510.     tmp >>= 1;
  511.     }
  512.     if (1 << power > interPtr->maxBytes) {
  513.     power++;
  514.     }
  515.     startPtr->hostMaxBytes = power;
  516.     /* 
  517.      * This part is kind of goofy.  The adapter expects the network
  518.      * address to be 7 bytes long (the first byte is missing). We have
  519.      * to bcopy the netAddress minus its first byte.
  520.      */
  521.     startPtr->netAddressSize = 7;
  522.     bcopy((char *) &interPtr->netAddress[NET_PROTO_RAW].generic.data[1],
  523.     (char *) &startPtr->netAddressBuf, sizeof(Net_Address)-1);
  524.     startPtr->netAddressBuf[0] = 0x49;
  525.     startPtr->netAddressBuf[5] = 0xfe;
  526.     status = NetUltraSendReq(statePtr, StandardDone, 
  527.         (ClientData) &startComplete, FALSE, 
  528.         0, (Net_ScatterGather *) NIL, sizeof(NetUltraStartRequest), 
  529.         &request);
  530.     if (status != SUCCESS) {
  531.     printf("NetUltraStart: unable to send start request\n");
  532.     goto exit;
  533.     }
  534.     Sync_MasterWait(&(startComplete), &(interPtr->mutex), FALSE);
  535.     if (hdrPtr->status & NET_ULTRA_STATUS_OK) {
  536.     if (netUltraDebug) {
  537.         printf("NetUltraStart: hdrPtr->status = %d : %s\n",
  538.         hdrPtr->status, GetStatusString(hdrPtr->status));
  539.     }
  540.     if (netUltraDebug) {
  541.         printf("Ultranet adapter started\n");
  542.         printf("Ucode %d\n", startPtr->ucodeRel);
  543.         printf("Adapter type %d, adapter hw %d\n", startPtr->adapterType,
  544.         startPtr->adapterHW);
  545.         printf("Max VC = %d\n", startPtr->maxVC);
  546.         printf("Max DRCV = %d\n", startPtr->maxDRCV);
  547.         printf("Max DSND = %d\n", startPtr->maxDSND);
  548.         printf("Slot = %d\n", startPtr->slot);
  549.         printf("Speed = %d\n", startPtr->speed);
  550.         printf("Max bytes = %d\n", startPtr->adapterMaxBytes);
  551.     }
  552.     if (startPtr->maxDRCV < statePtr->maxReadPending) {
  553.         printf("NetUltraStart: WARNING: max pending reads reset to %d\n",
  554.         startPtr->maxDRCV);
  555.         statePtr->maxReadPending = startPtr->maxDRCV;
  556.     }
  557.     if (startPtr->maxDSND < statePtr->maxWritePending) {
  558.         printf("NetUltraStart: WARNING: max pending writes reset to %d\n",
  559.         startPtr->maxDSND);
  560.         statePtr->maxWritePending = startPtr->maxDSND;
  561.     }
  562.     if (startPtr->adapterMaxBytes < power) {
  563.         interPtr->maxBytes = 1 << power;
  564.         printf("NetUltraStart: WARNING: max bytes reset to %d\n",
  565.         interPtr->maxBytes);
  566.     }
  567.     statePtr->flags = (NET_ULTRA_STATE_EXIST | NET_ULTRA_STATE_START |
  568.                 NET_ULTRA_STATE_NORMAL);
  569.     /*
  570.      * Now queue up pending reads. 
  571.      */
  572.     for (i = 0; i < statePtr->maxReadPending; i++) {
  573.         List_Links        *itemPtr;
  574.         Address    buffer;
  575.         itemPtr = List_First(statePtr->freeBufferList);
  576.         if (itemPtr == statePtr->freeBufferList) {
  577.         panic("NetUltraOutput: list screwup\n");
  578.         }
  579.         List_Remove(itemPtr);
  580.         buffer = BUFFER_TO_DVMA(itemPtr, statePtr);
  581.         status = NetUltraPendingRead(interPtr, statePtr->bufferSize,
  582.             buffer);
  583.         if (status != SUCCESS) {
  584.         printf("NetUltraStart: could not queue pending read.\n");
  585.         }
  586.     }
  587.     } else {
  588.     printf("NetUltraStart: start command failed <0x%x> : %s\n",
  589.         hdrPtr->status, GetStatusString(hdrPtr->status));
  590.     }
  591. exit:
  592.     return status;
  593. }
  594.  
  595. /*
  596.  *----------------------------------------------------------------------
  597.  *
  598.  * StandardDone --
  599.  *
  600.  *    This is a callback routine that is called from the interrupt
  601.  *    handler when "standard" commands complete. It copies the request
  602.  *    from the XRB in the queue to the request structure pointed
  603.  *    to by the XRB.  This allows the XRB to be used again.
  604.  *    If the data field in the info structure is not NIL then it
  605.  *    is assumed to be a pointer to a condition variable and a
  606.  *    broadcast is done on that variable.
  607.  *
  608.  *
  609.  * Results:
  610.  *    None.
  611.  *
  612.  * Side effects:
  613.  *    None.
  614.  *    
  615.  *
  616.  *----------------------------------------------------------------------
  617.  */
  618.  
  619. /* ARGSUSED */
  620. static void
  621. StandardDone(interPtr, infoPtr)
  622.     Net_Interface    *interPtr;    /* Interface. */
  623.     NetUltraXRBInfo    *infoPtr;    /* Info about XRB that completed. */
  624. {
  625.     bcopy((char *) &infoPtr->xrbPtr->request, (char *) infoPtr->requestPtr,
  626.     infoPtr->requestSize);
  627.     if (infoPtr->doneData != (ClientData) NIL) {
  628.     Sync_Broadcast((Sync_Condition *) infoPtr->doneData);
  629.     }
  630. }
  631.  
  632. /*
  633.  *----------------------------------------------------------------------
  634.  *
  635.  * NetUltraStop--
  636.  *
  637.  *    Send a stop request to the board.
  638.  *    Assumes the interface mutex is held.
  639.  *
  640.  * Results:
  641.  *    Standard Sprite return status.
  642.  *
  643.  * Side effects:
  644.  *    The adapter abandons what it is doing.
  645.  *
  646.  *----------------------------------------------------------------------
  647.  */
  648.  
  649. ReturnStatus
  650. NetUltraStop(statePtr)
  651.     NetUltraState    *statePtr;    /* State of the adapter. */
  652. {
  653.     NetUltraRequest        request;
  654.     NetUltraStopRequest        *stopPtr;
  655.     NetUltraRequestHdr        *hdrPtr;
  656.     Net_Interface        *interPtr;
  657.     ReturnStatus        status = SUCCESS;
  658.     Sync_Condition        stopComplete;
  659.  
  660.     interPtr = statePtr->interPtr;
  661.     stopPtr = &request.stop;
  662.     hdrPtr = &stopPtr->hdr;
  663.     if (!(statePtr->flags & NET_ULTRA_STATE_START)) {
  664.     printf("NetUltraStop: adapter not started.\n");
  665.     status = FAILURE;
  666.     goto exit;
  667.     }
  668.     bzero((char *) &request, sizeof(request));
  669.     hdrPtr->cmd = NET_ULTRA_STOP_REQ;
  670.     status = NetUltraSendReq(statePtr, StandardDone, 
  671.         (ClientData) &stopComplete, FALSE,
  672.         0, (Net_ScatterGather *) NIL, sizeof(NetUltraStopRequest), 
  673.         &request);
  674.     if (status != SUCCESS) {
  675.     printf("NetUltraStop: unable to send stop request\n");
  676.     goto exit;
  677.     }
  678.     Sync_MasterWait(&(stopComplete), &(interPtr->mutex), FALSE);
  679.     if (hdrPtr->status & NET_ULTRA_STATUS_OK) {
  680.     if (netUltraDebug) {
  681.         printf("NetUltraStop: hdrPtr->status = %d : %s\n",
  682.         hdrPtr->status, GetStatusString(hdrPtr->status));
  683.     }
  684.     statePtr->flags &= ~NET_ULTRA_STATE_START;
  685.     } else {
  686.     printf("NetUltraStop: stop command failed <0x%x> : %s\n",
  687.         hdrPtr->status, GetStatusString(hdrPtr->status));
  688.     }
  689. exit:
  690.     return status;
  691. }
  692.  
  693. /*
  694.  *----------------------------------------------------------------------
  695.  *
  696.  * NetUltraReset --
  697.  *
  698.  *    Resets the board by sending it a stop command followed by a
  699.  *    start command.  The XRB queues are also initialized.
  700.  *    Assumes the interface mutex is held.
  701.  *
  702.  * Results:
  703.  *    A standard Sprite return status.
  704.  *
  705.  * Side effects:
  706.  *    None.
  707.  *
  708.  *----------------------------------------------------------------------
  709.  */
  710.  
  711. ReturnStatus
  712. NetUltraReset(interPtr)
  713.     Net_Interface    *interPtr;    /* Interface to reset. */
  714. {
  715.     ReturnStatus    status = SUCCESS;
  716.     NetUltraState    *statePtr;    /* State of the adapter. */
  717.  
  718.     statePtr = (NetUltraState *) interPtr->interfaceData;
  719.     status = NetUltraStop(statePtr);
  720.     if (status != NULL) {
  721.     printf("NetUltraReset: stop failed\n");
  722.     return status;
  723.     }
  724.     InitQueues(statePtr);
  725.     status = NetUltraStart(statePtr);
  726.     if (status != NULL) {
  727.     printf("NetUltraReset: start failed\n");
  728.     return status;
  729.     }
  730.     return status;
  731. }
  732.  
  733. /*
  734.  *----------------------------------------------------------------------
  735.  *
  736.  * Net_UltraReset --
  737.  *
  738.  *    This is a version of the reset routine that can be called
  739.  *     from outside the module since it locks the mutex.
  740.  *
  741.  * Results:
  742.  *    
  743.  *
  744.  * Side effects:
  745.  *    None.
  746.  *
  747.  *----------------------------------------------------------------------
  748.  */
  749.  
  750. void
  751. Net_UltraReset(interPtr)
  752.     Net_Interface    *interPtr;    /* Interface to reset. */
  753. {
  754.     MASTER_LOCK(&interPtr->mutex);
  755.     /*
  756.      * If we are at interrupt level we have to do a callback to reset
  757.      * the adapter since we can't wait for the response from
  758.      * the adapter (there may not be a current process and we can't
  759.      * get the interrupt).
  760.      */
  761.     if (Mach_AtInterruptLevel()) {
  762.     Proc_CallFunc(NetUltraResetCallback, (ClientData) interPtr, 0);
  763.     } else {
  764.     (void) NetUltraReset(interPtr);
  765.     }
  766.     MASTER_UNLOCK(&interPtr->mutex);
  767. }
  768.  
  769. /*
  770.  *----------------------------------------------------------------------
  771.  *
  772.  * NetUltraResetCallback --
  773.  *
  774.  *    This routine is called by the Proc_ServerProc during the
  775.  *    callback to reset the adapter.
  776.  *
  777.  * Results:
  778.  *    None.
  779.  *
  780.  * Side effects:
  781.  *    The adapter is reset.
  782.  *
  783.  *----------------------------------------------------------------------
  784.  */
  785.  
  786. static void
  787. NetUltraResetCallback(data, infoPtr)
  788.     ClientData        data;        /* Ptr to the interface to reset. */
  789.     Proc_CallInfo    *infoPtr;    /* Unused. */
  790. {
  791.     Net_UltraReset((Net_Interface *) data);
  792. }
  793.  
  794.  
  795. /*
  796.  *----------------------------------------------------------------------
  797.  *
  798.  * Net_UltraHardReset --
  799.  *
  800.  *    This is a version of the hard reset routine that can be called from
  801.  *     outside the net module because it does not assume that a
  802.  *    lock is held (or interrupts are disabled) when it is called.
  803.  *
  804.  * Results:
  805.  *    None.
  806.  *
  807.  * Side effects:
  808.  *    The adapter is reset.
  809.  *
  810.  *----------------------------------------------------------------------
  811.  */
  812.  
  813. void
  814. Net_UltraHardReset(interPtr)
  815.     Net_Interface    *interPtr;    /* Interface to reset. */
  816. {
  817.     MASTER_LOCK(&interPtr->mutex);
  818.  
  819.     NetUltraHardReset(interPtr);
  820.  
  821.     MASTER_UNLOCK(&interPtr->mutex);
  822. }
  823.  
  824.  
  825. /*
  826.  *----------------------------------------------------------------------
  827.  *
  828.  * NetUltraDiag --
  829.  *
  830.  *    Send a diagnostic command to the adapter.
  831.  *
  832.  * Results:
  833.  *    SUCCESS if the adapter processed the command correctly,
  834.  *    FAILURE otherwise.
  835.  *
  836.  * Side effects:
  837.  *    The adapter is sent a diagnostic command.
  838.  *
  839.  *----------------------------------------------------------------------
  840.  */
  841.  
  842. ReturnStatus
  843. NetUltraDiag(statePtr, cmdPtr)
  844.     NetUltraState    *statePtr;    /* State of the adapter. */
  845.     NetUltraDiagCommand    *cmdPtr;    /* Diagnostic command block. */
  846. {
  847.     ReturnStatus        status = SUCCESS;
  848.     NetUltraDiagCommand        tmpCmd;    
  849.     int                inSize;
  850.     int                outSize;
  851.     int                fmtStatus;
  852.  
  853.     MASTER_LOCK(&statePtr->interPtr->mutex);
  854.     if (!(statePtr->flags & NET_ULTRA_STATE_EPROM)) {
  855.     if (netUltraDebug) {
  856.         printf("NetUltraDiag: device is not in EPROM state.\n");
  857.     }
  858.     status = FAILURE;
  859.     goto exit;
  860.     }
  861.     if (netUltraDebug) {
  862.     printf("Sending diagnostic command to adapter.\n");
  863.     }
  864.     bzero((char *) &tmpCmd, sizeof(tmpCmd));
  865.     tmpCmd.opcode = NET_ULTRA_DIAG_OPCODE;
  866.     status = NetUltraSendCmd(statePtr, NET_ULTRA_DIAG_OK, 
  867.             sizeof(tmpCmd), (Address) &tmpCmd);
  868.     if (status != SUCCESS) {
  869.     goto exit;
  870.     }
  871.     cmdPtr->reply = tmpCmd.reply;
  872.     cmdPtr->version = tmpCmd.version;
  873.     cmdPtr->error = tmpCmd.error;
  874.     /*
  875.      * The hardware related fields are returned in Intel 386 byte-order.
  876.      */
  877.     inSize = 5 * sizeof(int);
  878.     outSize = inSize;
  879.     fmtStatus = Fmt_Convert("w5", NET_ULTRA_FORMAT, &inSize, 
  880.             (char *) &(tmpCmd.hwModel), mach_Format, &outSize, 
  881.             (char *) &(cmdPtr->hwModel));
  882.     if (fmtStatus != 0) {
  883.     printf("NetUltraInfo: Format returned %d\n");
  884.     status = FAILURE;
  885.     goto exit;
  886.     }
  887. exit:
  888.     MASTER_UNLOCK(&statePtr->interPtr->mutex)
  889.     return status;
  890. }
  891.  
  892. /*
  893.  *----------------------------------------------------------------------
  894.  *
  895.  * NetUltraInfo --
  896.  *
  897.  *    Send an info command to the adapter. The results are the same
  898.  *     as the diagnostic command, except the diagnostics are not 
  899.  *    actually run.  Presumably we are fetching the results of the
  900.  *    last time diagnostics were run, probably due to a reset.
  901.  *
  902.  * Results:
  903.  *    SUCCESS if the adapter processed the command correctly,
  904.  *    FAILURE otherwise.
  905.  *
  906.  * Side effects:
  907.  *    The adapter is sent an info command.
  908.  *
  909.  *----------------------------------------------------------------------
  910.  */
  911.  
  912. ReturnStatus
  913. NetUltraInfo(statePtr, cmdPtr)
  914.     NetUltraState    *statePtr;    /* State of the adapter. */
  915.     NetUltraInfoCommand    *cmdPtr;    /* Info command block. */
  916. {
  917.     ReturnStatus        status = SUCCESS;
  918.     int                fmtStatus;
  919.     NetUltraInfoCommand        tmpCmd;
  920.     int                inSize;
  921.     int                outSize;
  922.  
  923.     MASTER_LOCK(&statePtr->interPtr->mutex);
  924.     if (!(statePtr->flags & NET_ULTRA_STATE_EPROM)) {
  925.     if (netUltraDebug) {
  926.         printf("NetUltraInfo: device is not in EPROM state.\n");
  927.     }
  928.     status = FAILURE;
  929.     goto exit;
  930.     }
  931.     if (netUltraDebug) {
  932.     printf("Sending Info command to adapter.\n");
  933.     }
  934.     bzero((char *) &tmpCmd, sizeof(NetUltraInfoCommand));
  935.     tmpCmd.opcode = NET_ULTRA_INFO_OPCODE;
  936.     status = NetUltraSendCmd(statePtr, NET_ULTRA_INFO_OK, 
  937.             sizeof(NetUltraInfoCommand), (Address) &tmpCmd);
  938.     if (status != SUCCESS) {
  939.     goto exit;
  940.     }
  941.     cmdPtr->reply = tmpCmd.reply;
  942.     cmdPtr->version = tmpCmd.version;
  943.     cmdPtr->error = tmpCmd.error;
  944.     /*
  945.      * The hardware related fields are returned in Intel 386 byte-order.
  946.      */
  947.     inSize = 5 * sizeof(int);
  948.     outSize = inSize;
  949.     fmtStatus = Fmt_Convert("w5", NET_ULTRA_FORMAT, &inSize, 
  950.             (char *) &(tmpCmd.hwModel), mach_Format, &outSize, 
  951.             (char *) &(cmdPtr->hwModel));
  952.     if (fmtStatus != 0) {
  953.     printf("NetUltraInfo: Format returned %d\n");
  954.     status = FAILURE;
  955.     }
  956. exit:
  957.     MASTER_UNLOCK(&statePtr->interPtr->mutex)
  958.     return status;
  959. }
  960.  
  961. /*
  962.  *----------------------------------------------------------------------
  963.  *
  964.  * NetUltraExtDiag --
  965.  *
  966.  *    Send an extended diagnostic command to the adapter.
  967.  *
  968.  * Results:
  969.  *    SUCCESS if the adapter processed the command correctly,
  970.  *    FAILURE otherwise.
  971.  *
  972.  * Side effects:
  973.  *    The adapter is sent an extended diagnostic command.
  974.  *
  975.  *----------------------------------------------------------------------
  976.  */
  977.  
  978. ReturnStatus
  979. NetUltraExtDiag(statePtr, external, buffer, cmdPtr)
  980.     NetUltraState    *statePtr;    /* State of the adapter. */
  981.     Boolean        external;    /* TRUE => use external loopback
  982.                      * adapter. */
  983.     char        buffer[];     /* Used for VME tests. */
  984.     NetUltraExtDiagCommand    *cmdPtr;    /* Extended diagnostic command
  985.                          * block. */
  986. {
  987.     ReturnStatus        status = SUCCESS;
  988.     Address            bufAddress;
  989.  
  990.     MASTER_LOCK(&statePtr->interPtr->mutex);
  991.     if (!(statePtr->flags & NET_ULTRA_STATE_EPROM)) {
  992.     if (netUltraDebug) {
  993.         printf("NetUltraExtDiag: device is not in EPROM state.\n");
  994.     }
  995.     status = FAILURE;
  996.     goto exit;
  997.     }
  998.     if (netUltraDebug) {
  999.     printf("Sending extended diagnostic command to adapter.\n");
  1000.     }
  1001.     bufAddress = (Address) VmMach_DMAAlloc(NET_ULTRA_EXT_DIAG_BUF_SIZE, buffer);
  1002.     if (bufAddress == (Address) NIL) {
  1003.     printf("NetUltraExtDiag: unable to allocate buffer in DMA space.\n");
  1004.     status = FAILURE;
  1005.     }
  1006.     bzero((char *) cmdPtr, sizeof(*cmdPtr));
  1007.     cmdPtr->opcode = NET_ULTRA_EXT_DIAG_OPCODE;
  1008.     cmdPtr->externalLoopback = (external == TRUE) ? 1 : 0;
  1009.     cmdPtr->bufferAddress = (int) DVMA_TO_VME(bufAddress, statePtr);
  1010.     status = NetUltraSendCmd(statePtr, NET_ULTRA_EXT_DIAG_OK, sizeof(*cmdPtr), 
  1011.         (Address) cmdPtr);
  1012.     VmMach_DMAFree(NET_ULTRA_EXT_DIAG_BUF_SIZE, bufAddress);
  1013. exit:
  1014.     MASTER_UNLOCK(&statePtr->interPtr->mutex);
  1015.     return status;
  1016. }
  1017.  
  1018. /*
  1019.  *----------------------------------------------------------------------
  1020.  *
  1021.  * NetUltraLoad --
  1022.  *
  1023.  *    Download a block of ucode onto the adapter.
  1024.  *
  1025.  * Results:
  1026.  *    SUCCESS if the command was processed properly
  1027.  *
  1028.  * Side effects:
  1029.  *    Data is loaded into the adapter ram.
  1030.  *
  1031.  *----------------------------------------------------------------------
  1032.  */
  1033.  
  1034. ReturnStatus
  1035. NetUltraLoad(statePtr, address, length, ucodePtr)
  1036.     NetUltraState    *statePtr;    /* State of the adapter. */
  1037.     int            address;    /* Load address of ucode. */
  1038.     int            length;        /* Size of ucode. */
  1039.     Address        ucodePtr;    /* Ucode buffer. */
  1040. {
  1041.     NetUltraLoadCommand        cmd;
  1042.     int                inSize;
  1043.     int                outSize;
  1044.     int                fmtStatus;
  1045.     Address            dmaAddress;
  1046.     ReturnStatus        status = SUCCESS;
  1047.  
  1048.     MASTER_LOCK(&statePtr->interPtr->mutex);
  1049.     if (!(statePtr->flags & NET_ULTRA_STATE_EPROM)) {
  1050.     if (netUltraDebug) {
  1051.         printf("NetUltraExtDiag: device is not in EPROM state.\n");
  1052.     }
  1053.     status = FAILURE;
  1054.     goto exit;
  1055.     }
  1056.     if (netUltraDebug) {
  1057.     printf("Sending load command to adapter.\n");
  1058.     printf("Address = 0x%x, length = %d\n", address, length);
  1059.     }
  1060.     /*
  1061.      * Convert the address and length to Intel format.
  1062.      */
  1063.     inSize = sizeof(int);
  1064.     outSize = sizeof(int);
  1065.     fmtStatus = Fmt_Convert("w", mach_Format, &inSize,
  1066.             (char *) &address, NET_ULTRA_FORMAT, &outSize,
  1067.             (char *) &(cmd.loadAddress));
  1068.     if (fmtStatus != 0) {
  1069.     printf("NetUltraLoad: Fmt_Convert returned %d\n",
  1070.         fmtStatus);
  1071.     status = FAILURE;
  1072.     goto exit;
  1073.     }
  1074.     inSize = sizeof(int);
  1075.     outSize = sizeof(int);
  1076.     fmtStatus = Fmt_Convert("w", mach_Format, &inSize,
  1077.             (char *) &length, NET_ULTRA_FORMAT, &outSize,
  1078.             (char *) &(cmd.length));
  1079.     if (fmtStatus != 0) {
  1080.     printf("NetUltraLoad: Fmt_Convert returned %d\n",
  1081.         fmtStatus);
  1082.     status = FAILURE;
  1083.     goto exit;
  1084.     }
  1085.     cmd.opcode = NET_ULTRA_LOAD_OPCODE;
  1086.     cmd.reply = 0;
  1087.     /*
  1088.      * Map the ucode into DVMA space.
  1089.      */
  1090.     dmaAddress = (Address) VmMach_DMAAlloc(length, ucodePtr); 
  1091.     cmd.dataAddress = (unsigned long) DVMA_TO_VME(dmaAddress, statePtr);
  1092.     status = NetUltraSendCmd(statePtr, NET_ULTRA_LOAD_OK, sizeof(cmd), 
  1093.         (Address) &cmd);
  1094.     VmMach_DMAFree(length, dmaAddress);
  1095.     if (status != SUCCESS) {
  1096.     goto exit;
  1097.     }
  1098.     statePtr->flags |= NET_ULTRA_STATE_LOAD;
  1099. exit:
  1100.     MASTER_UNLOCK(&statePtr->interPtr->mutex)
  1101.     return status;
  1102. }
  1103.  
  1104. /*
  1105.  *----------------------------------------------------------------------
  1106.  *
  1107.  * NetUltraGo --
  1108.  *
  1109.  *    Send the go command to the adapter to start its processor
  1110.  *    running the ucode.
  1111.  *
  1112.  * Results:
  1113.  *    SUCCESS if it worked, FAILURE otherwise
  1114.  *
  1115.  * Side effects:
  1116.  *    The adapter cpu begins executing.
  1117.  *
  1118.  *----------------------------------------------------------------------
  1119.  */
  1120.  
  1121. ReturnStatus
  1122. NetUltraGo(statePtr, address)
  1123.     NetUltraState    *statePtr;    /* State of the adapter. */
  1124.     int            address;    /* Start address. */
  1125. {
  1126.     NetUltraGoCommand        cmd;
  1127.     int                inSize;
  1128.     int                outSize;
  1129.     int                fmtStatus;
  1130.     ReturnStatus        status = SUCCESS;
  1131.  
  1132.     MASTER_LOCK(&statePtr->interPtr->mutex);
  1133.     if (!(statePtr->flags & NET_ULTRA_STATE_EPROM)) {
  1134.     if (netUltraDebug) {
  1135.         printf("NetUltraExtDiag: device is not in EPROM state.\n");
  1136.     }
  1137.     status = FAILURE;
  1138.     goto exit;
  1139.     }
  1140.     if (!(statePtr->flags & NET_ULTRA_STATE_LOAD)) {
  1141.     if (netUltraDebug) {
  1142.         printf("NetUltraGo: ucode not downloaded.\n");
  1143.     }
  1144.     status = FAILURE;
  1145.     goto exit;
  1146.     }
  1147.     if (netUltraDebug) {
  1148.     printf("Sending go command to adapter.\n");
  1149.     }
  1150.     /*
  1151.      * Convert the address into Intel format.
  1152.      */
  1153.     inSize = sizeof(int);
  1154.     outSize = sizeof(int);
  1155.     fmtStatus = Fmt_Convert("w", mach_Format, &inSize,
  1156.             (char *) &address, NET_ULTRA_FORMAT, &outSize,
  1157.             (char *) &(cmd.startAddress));
  1158.     if (fmtStatus != 0) {
  1159.     printf("NetUltraGo: Fmt_Convert returned %d\n",
  1160.         fmtStatus);
  1161.     status = FAILURE;
  1162.     goto exit;
  1163.     }
  1164.     cmd.opcode = NET_ULTRA_GO_OPCODE;
  1165.     cmd.reply = 0;
  1166.     status = NetUltraSendCmd(statePtr, NET_ULTRA_GO_OK, sizeof(cmd), 
  1167.         (Address) &cmd);
  1168.     if (status != SUCCESS) {
  1169.     goto exit;
  1170.     }
  1171.     statePtr->flags &= ~NET_ULTRA_STATE_LOAD;
  1172.     statePtr->flags |= NET_ULTRA_STATE_GO;
  1173.     statePtr->flags &= ~NET_ULTRA_STATE_EPROM;
  1174. exit:
  1175.     MASTER_UNLOCK(&statePtr->interPtr->mutex)
  1176.     return status;
  1177. }
  1178.  
  1179.  
  1180. /*
  1181.  *----------------------------------------------------------------------
  1182.  *
  1183.  * NetUltraSendCmd --
  1184.  *
  1185.  *    Send a command to the adapter.
  1186.  *
  1187.  * Results:
  1188.  *    SUCCESS if the adapter responded to the command,
  1189.  *    DEV_TIMEOUT if the adapter did not respond
  1190.  *
  1191.  * Side effects:
  1192.  *    A command is sent to the adapter.
  1193.  *
  1194.  *----------------------------------------------------------------------
  1195.  */
  1196.  
  1197. ReturnStatus
  1198. NetUltraSendCmd(statePtr, ok,size, cmdPtr)
  1199.     NetUltraState    *statePtr;    /* State of the adapter. */
  1200.     int            ok;        /* Value of reply field if command
  1201.                      * was successful. */
  1202.     int            size;        /* Size of command block. */
  1203.     Address        cmdPtr;        /* The command block. */
  1204. {
  1205.     struct StdCmd {
  1206.     volatile int        opcode;
  1207.     volatile int        reply;
  1208.     } *stdCmdPtr;
  1209.     ReturnStatus    status = SUCCESS;
  1210.  
  1211.     stdCmdPtr = (struct StdCmd *) cmdPtr;
  1212.     if (netUltraDebug) {
  1213.     printf("NetUltraSendCmd: sending command %d to adapter\n",
  1214.         stdCmdPtr->opcode);
  1215.     printf("NetUltraSendCmd: cmdPtr = 0x%x\n", cmdPtr);
  1216.     }
  1217.     if ((int) cmdPtr & 0x3) {
  1218.     panic("NetUltraSendCmd: command not aligned on a word boundary\n");
  1219.     }
  1220.     stdCmdPtr->reply = 0;
  1221.     cmdPtr = VmMach_DMAAlloc(size, cmdPtr);
  1222.     if (cmdPtr == (Address) NIL) {
  1223.     panic("NetUltraSendCmd: can't allocate DMA space for command\n");
  1224.     }
  1225.     if (netUltraDebug) {
  1226.     printf("NetUltraSendCmd: cmdPtr mapped into DMA space\n");
  1227.     printf("NetUltraSendCmd: cmdPtr = 0x%x\n", cmdPtr);
  1228.     }
  1229.     *statePtr->intrReg = 
  1230.     (int) DVMA_TO_VME(cmdPtr,statePtr);
  1231.     WAIT_FOR_REPLY(&stdCmdPtr->reply, NET_ULTRA_DELAY);
  1232.     VmMach_DMAFree(size, cmdPtr);
  1233.     if (stdCmdPtr->reply == 0) {
  1234.     printf("NetUltraSendCmd: adapter timed out\n");
  1235.     status = DEV_TIMEOUT;
  1236.     } else if (stdCmdPtr->reply == ok) {
  1237.     status = SUCCESS;
  1238.     } else {
  1239.     printf("NetUltraSendCmd: adapter returned %d\n", stdCmdPtr->reply);
  1240.     status = FAILURE;
  1241.     }
  1242.     return status;
  1243. }
  1244.  
  1245. /*
  1246.  *----------------------------------------------------------------------
  1247.  *
  1248.  * NetUltraIntr --
  1249.  *
  1250.  *    Handle an interrupt from the Ultranet adapter.
  1251.  *
  1252.  * Results:
  1253.  *    None.
  1254.  *
  1255.  * Side effects:
  1256.  *    None.
  1257.  *
  1258.  *----------------------------------------------------------------------
  1259.  */
  1260.  
  1261. /*ARGSUSED*/
  1262. void
  1263. NetUltraIntr(interPtr, polling)
  1264.     Net_Interface    *interPtr;    /* Interface to process. */
  1265.     Boolean        polling;    /* TRUE if are being polled instead of
  1266.                      * processing an interrupt. */
  1267. {
  1268.     NetUltraXRB        *xrbPtr;
  1269.     NetUltraXRB        *nextXRBPtr;
  1270.     NetUltraState    *statePtr;
  1271.     NetUltraDMAInfo    *dmaPtr;
  1272.     NetUltraRequestHdr  *hdrPtr;
  1273.     NetUltraXRBInfo    *infoPtr;
  1274.     int            processed;
  1275.     NetUltraTraceInfo    *tracePtr;
  1276.     Address        buffer;
  1277.  
  1278.     MASTER_LOCK(&interPtr->mutex);
  1279. #ifndef CLEAN
  1280.     if (netUltraDebug) {
  1281.     printf("Received an Ultranet interrupt.\n");
  1282.     }
  1283. #endif
  1284.     statePtr = (NetUltraState *) interPtr->interfaceData;
  1285.     xrbPtr = statePtr->nextToHostPtr;
  1286. #ifndef CLEAN
  1287.     if (netUltraTrace) {
  1288.     NEXT_TRACE(statePtr, &tracePtr);
  1289.     tracePtr->event = INTERRUPT;
  1290.     Timer_GetCurrentTicks(&tracePtr->ticks);
  1291.     }
  1292. #endif
  1293.     processed = 0;
  1294.     while(xrbPtr->filled != 0) {
  1295.     /*
  1296.      * Compute the next xrb to the host.
  1297.      */
  1298.     if (xrbPtr == statePtr->lastToHostPtr) {
  1299.         nextXRBPtr = statePtr->firstToHostPtr;
  1300.     } else {
  1301.         nextXRBPtr = xrbPtr + 1;
  1302.     }
  1303.     statePtr->nextToHostPtr = nextXRBPtr;
  1304.     dmaPtr = &xrbPtr->dma;
  1305.     if (!(dmaPtr->cmd & NET_ULTRA_DMA_CMD_FROM_ADAPTER)) {
  1306.         printf("NetUltraIntr: cmd (0x%x) not from adapter?\n", dmaPtr->cmd);
  1307.         goto endLoop;
  1308.     }
  1309.     if ((dmaPtr->cmd & NET_ULTRA_DMA_CMD_MASK) != NET_ULTRA_DMA_CMD_XRB) {
  1310.         printf("NetUltraIntr: dmaPtr->cmd = 0x%x\n", dmaPtr->cmd);
  1311.         goto endLoop;
  1312.     }
  1313.     hdrPtr = (NetUltraRequestHdr *) &xrbPtr->request;
  1314.     infoPtr = hdrPtr->infoPtr;
  1315.     if (infoPtr->flags & NET_ULTRA_INFO_PENDING) {
  1316. #ifndef CLEAN
  1317.         if (netUltraDebug) {
  1318.         printf("NetUltraIntr: processing 0x%x\n", infoPtr);
  1319.         }
  1320.         if (netUltraTrace) {
  1321.         NEXT_TRACE(statePtr, &tracePtr);
  1322.         tracePtr->event = PROCESS_XRB;
  1323.         tracePtr->index = xrbPtr - statePtr->firstToHostPtr;
  1324.         tracePtr->infoPtr = infoPtr;
  1325.         Timer_GetCurrentTicks(&tracePtr->ticks);
  1326.         }
  1327. #endif
  1328.         infoPtr->xrbPtr = xrbPtr;
  1329.         if (statePtr->flags & NET_ULTRA_STATE_STATS) {
  1330.         if (hdrPtr->cmd == NET_ULTRA_DGRAM_RECV_REQ) {
  1331.             statePtr->stats.packetsReceived++;
  1332.             statePtr->stats.bytesReceived += hdrPtr->size;
  1333.             statePtr->stats.receivedHistogram[hdrPtr->size >> 10]++;
  1334.         }
  1335.         }
  1336.         /*
  1337.          * Mark the info as not pending.
  1338.          * Clearing the pending bit ensures
  1339.          * that this packet does not get processed twice, since the
  1340.          * master lock around the interface will get released before
  1341.          * calling the RPC system, so that the RPC system can
  1342.          * output a packet. Do not
  1343.          * clear the filled bit since we are using the contents of
  1344.          * the xrb and we don't want the adapter to overwrite it
  1345.          * yet. 
  1346.          */
  1347.         infoPtr->flags &= ~NET_ULTRA_INFO_PENDING;
  1348.         if (infoPtr->doneProc != NILPROC) {
  1349.         (infoPtr->doneProc)(interPtr, infoPtr);
  1350.         }
  1351.         if (infoPtr->flags & NET_ULTRA_INFO_STD_BUFFER) {
  1352.         if (infoPtr->flags & NET_ULTRA_INFO_REMAP) {
  1353.             VmMach_DMAFree(hdrPtr->size, 
  1354.             VME_TO_DVMA(hdrPtr->buffer, statePtr));
  1355.             buffer = infoPtr->buffer;
  1356.         } else {
  1357.             buffer = VME_TO_BUFFER(hdrPtr->buffer, statePtr);
  1358.         }
  1359.         List_InitElement((List_Links *) buffer);
  1360.         List_Insert((List_Links *) buffer,
  1361.                LIST_ATREAR(statePtr->freeBufferList));
  1362.         }
  1363.         List_Remove((List_Links *) infoPtr);
  1364.         List_Insert((List_Links *) infoPtr, 
  1365.         LIST_ATREAR(statePtr->freeXRBInfoList));
  1366.         processed++;
  1367.     } else {
  1368. #ifndef CLEAN
  1369.         if (netUltraTrace) {
  1370.         NEXT_TRACE(statePtr, &tracePtr);
  1371.         tracePtr->event = INFO_NOT_PENDING;
  1372.         tracePtr->index = xrbPtr - statePtr->firstToHostPtr;
  1373.         tracePtr->infoPtr = infoPtr;
  1374.         }
  1375. #endif
  1376.     }
  1377. endLoop: 
  1378.     xrbPtr->filled = 0;
  1379.     xrbPtr = nextXRBPtr;
  1380.     /*
  1381.      * Check and see if there is a free xrb in the "to adapter"
  1382.      * queue.  Presumably the appearance of one in the "to host"
  1383.      * queue implies one freed up in the "to adapter" queue.
  1384.      */
  1385.     if ((statePtr->nextToAdapterPtr->filled != 0) && 
  1386.         (statePtr->toAdapterAvail.waiting == TRUE)) {
  1387.         Sync_Broadcast(&statePtr->toAdapterAvail);
  1388.     }
  1389.     }
  1390. #ifndef CLEAN
  1391.     if (processed == 0) {
  1392.     if (netUltraDebug) {
  1393.         printf("NetUltraIntr: didn't process any packets.\n");
  1394.     }
  1395.     }
  1396. #endif
  1397.     MASTER_UNLOCK(&interPtr->mutex);
  1398. }
  1399.  
  1400. /*
  1401.  *----------------------------------------------------------------------
  1402.  *
  1403.  * NetUltraIOControl --
  1404.  *
  1405.  *    Handle ioctls for the Ultranet adapter..
  1406.  *
  1407.  * Results:
  1408.  *    SUCCESS if the ioctl was performed successfully, a standard
  1409.  *    Sprite error code otherwise.
  1410.  *
  1411.  * Side effects:
  1412.  *    Commands may be sent to the adapter and the adapter state
  1413.  *    may change.
  1414.  *
  1415.  *----------------------------------------------------------------------
  1416.  */
  1417.  
  1418. /*ARGSUSED*/
  1419. ReturnStatus
  1420. NetUltraIOControl(interPtr, ioctlPtr, replyPtr)
  1421.     Net_Interface *interPtr;    /* Interface on which to perform ioctl. */
  1422.     Fs_IOCParam *ioctlPtr;    /* Standard I/O Control parameter block */
  1423.     Fs_IOReply *replyPtr;    /* Size of outBuffer and returned signal */
  1424. {
  1425.     ReturnStatus status = SUCCESS;
  1426.     int    fmtStatus;
  1427.     int inSize;
  1428.     int outSize;
  1429.     NetUltraState    *statePtr = (NetUltraState *) interPtr->interfaceData;
  1430.  
  1431.     if (netUltraDebug) {
  1432.     printf("NetUltraIOControl: command = %d\n", ioctlPtr->command);
  1433.     }
  1434.     if ((ioctlPtr->command & ~0xffff) != IOC_ULTRA) {
  1435.     return DEV_INVALID_ARG;
  1436.     }
  1437.     switch(ioctlPtr->command) {
  1438.     case IOC_ULTRA_SET_FLAGS:
  1439.     case IOC_ULTRA_RESET_FLAGS:
  1440.     case IOC_ULTRA_GET_FLAGS:
  1441.         return GEN_NOT_IMPLEMENTED;
  1442.         break;
  1443.     case IOC_ULTRA_CLR:
  1444.     case IOC_ULTRA_INT:
  1445.     case IOC_ULTRA_WFI:
  1446.         return DEV_INVALID_ARG;
  1447.         break;
  1448.     case IOC_ULTRA_DUMP:
  1449.         return GEN_NOT_IMPLEMENTED;
  1450.         break;
  1451.     case IOC_ULTRA_DEBUG: {
  1452.         int    value;
  1453.         outSize = sizeof(int);
  1454.         inSize = ioctlPtr->inBufSize;
  1455.         fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize,
  1456.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1457.                 (Address) &value);
  1458.         if (fmtStatus != 0) {
  1459.         printf("Format of IOC_ULTRA_DEBUG parameter failed, 0x%x\n",
  1460.             fmtStatus);
  1461.         return GEN_INVALID_ARG;
  1462.         }
  1463.         netUltraDebug = value;
  1464.         break;
  1465.     }
  1466.     case IOC_ULTRA_TRACE: {
  1467.         int    value;
  1468.         outSize = sizeof(int);
  1469.         inSize = ioctlPtr->inBufSize;
  1470.         fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize,
  1471.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1472.                 (Address) &value);
  1473.         if (fmtStatus != 0) {
  1474.         printf("Format of IOC_ULTRA_TRACE parameter failed, 0x%x\n",
  1475.             fmtStatus);
  1476.         return GEN_INVALID_ARG;
  1477.         }
  1478.         netUltraTrace = value;
  1479.         break;
  1480.     }
  1481.     case IOC_ULTRA_RESET: 
  1482.         Net_UltraReset(interPtr);
  1483.         break;
  1484.     case IOC_ULTRA_HARD_RESET:
  1485.         Net_UltraHardReset(interPtr);
  1486.         break;
  1487.     case IOC_ULTRA_GET_ADAP_INFO: {
  1488.         NetUltraInfoCommand        cmd;
  1489.         Dev_UltraAdapterInfo    info;
  1490.  
  1491.         status = NetUltraInfo(statePtr, &cmd);
  1492.         if (status != SUCCESS) {
  1493.         return status;
  1494.         }
  1495.         info.version = cmd.version;
  1496.         info.error = cmd.error;
  1497.         info.hwModel = cmd.hwModel;
  1498.         info.hwVersion = cmd.hwVersion;
  1499.         info.hwRevision = cmd.hwRevision;
  1500.         info.hwOption = cmd.hwOption;
  1501.         info.hwSerial = cmd.hwSerial;
  1502.         inSize = sizeof(info);
  1503.         outSize = ioctlPtr->outBufSize;
  1504.         fmtStatus = Fmt_Convert("{w7}", mach_Format, &inSize,
  1505.         (Address) &info, ioctlPtr->format, &outSize,
  1506.         (Address) ioctlPtr->outBuffer);
  1507.         if (fmtStatus != 0) {
  1508.         if (fmtStatus == FMT_OUTPUT_TOO_SMALL) {
  1509.             return GEN_INVALID_ARG;
  1510.         } else {
  1511.             printf(
  1512.             "NetUltraIOControl: Fmt_Convert returned %d\n",
  1513.             fmtStatus);
  1514.             return FAILURE;
  1515.         }
  1516.         }
  1517.         break;
  1518.     }
  1519.     case IOC_ULTRA_DIAG: {
  1520.         NetUltraDiagCommand        cmd;
  1521.         Dev_UltraDiag        diag;
  1522.  
  1523.         status = NetUltraDiag(statePtr, &cmd);
  1524.         if (status != SUCCESS) {
  1525.         return status;
  1526.         }
  1527.         diag.version = cmd.version;
  1528.         diag.error = cmd.error;
  1529.         diag.hwModel = cmd.hwModel;
  1530.         diag.hwVersion = cmd.hwVersion;
  1531.         diag.hwRevision = cmd.hwRevision;
  1532.         diag.hwOption = cmd.hwOption;
  1533.         diag.hwSerial = cmd.hwSerial;
  1534.         inSize = sizeof(diag);
  1535.         outSize = ioctlPtr->outBufSize;
  1536.         fmtStatus = Fmt_Convert("{w7}", mach_Format, &inSize,
  1537.         (Address) &diag, ioctlPtr->format, &outSize,
  1538.         (Address) ioctlPtr->outBuffer);
  1539.         if (fmtStatus != 0) {
  1540.         if (fmtStatus == FMT_OUTPUT_TOO_SMALL) {
  1541.             return GEN_INVALID_ARG;
  1542.         } else {
  1543.             printf(
  1544.             "NetUltraIOControl: Fmt_Convert returned %d\n",
  1545.             fmtStatus);
  1546.             return FAILURE;
  1547.         }
  1548.         }
  1549.         break;
  1550.     }
  1551.     case IOC_ULTRA_EXTENDED_DIAG: {
  1552.         NetUltraExtDiagCommand    cmd;
  1553.         Dev_UltraExtendedDiag    extDiag;
  1554.         char            *buffer;
  1555.  
  1556.         buffer = (char *) malloc(NET_ULTRA_EXT_DIAG_BUF_SIZE);
  1557.         inSize = ioctlPtr->inBufSize;
  1558.         outSize = sizeof(extDiag);
  1559.         fmtStatus = Fmt_Convert("{w3}", ioctlPtr->format, &inSize,
  1560.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1561.                 (Address) &extDiag);
  1562.         if (fmtStatus != 0) {
  1563.         if (fmtStatus == FMT_INPUT_TOO_SMALL) {
  1564.             return GEN_INVALID_ARG;
  1565.         } else {
  1566.             printf("NetUltraIOControl: Fmt_Convert returned %d\n",
  1567.             fmtStatus);
  1568.             return FAILURE;
  1569.         }
  1570.         }
  1571.         status = NetUltraExtDiag(statePtr, extDiag.externalLoopback, 
  1572.                 buffer,&cmd);
  1573.         free(buffer);
  1574.         if (status != SUCCESS) {
  1575.         return status;
  1576.         }
  1577.         extDiag.version = cmd.version;
  1578.         extDiag.error = cmd.error;
  1579.         inSize = sizeof(extDiag);
  1580.         outSize = ioctlPtr->outBufSize;
  1581.         fmtStatus = Fmt_Convert("{w3}", mach_Format, &inSize,
  1582.         (Address) &extDiag, ioctlPtr->format, &outSize,
  1583.         (Address) ioctlPtr->outBuffer);
  1584.         if (fmtStatus != 0) {
  1585.         if (fmtStatus == FMT_OUTPUT_TOO_SMALL) {
  1586.             return GEN_INVALID_ARG;
  1587.         } else {
  1588.             printf(
  1589.             "NetUltraIOControl: Fmt_Convert returned %d\n",
  1590.             fmtStatus);
  1591.             return FAILURE;
  1592.         }
  1593.         }
  1594.         break;
  1595.     }
  1596.     case IOC_ULTRA_LOAD: {
  1597.         Dev_UltraLoad        load;
  1598.         Address            ucodePtr;
  1599.         inSize = 2 * sizeof(int);
  1600.         outSize = sizeof(load);
  1601.         fmtStatus = Fmt_Convert("w2", ioctlPtr->format, &inSize,
  1602.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1603.                 (Address) &load);
  1604.         if (fmtStatus != 0) {
  1605.         if (fmtStatus == FMT_INPUT_TOO_SMALL) {
  1606.             return GEN_INVALID_ARG;
  1607.         } else {
  1608.             printf("NetUltraIOControl: Fmt_Convert returned %d\n",
  1609.             fmtStatus);
  1610.             return FAILURE;
  1611.         }
  1612.         }
  1613.         /*
  1614.          * This assumes that there isn't any padding between the
  1615.          * two integers in NetUltraLoadCommand and the data buffer.
  1616.          */
  1617.         ucodePtr = (Address) ioctlPtr->inBuffer + inSize;
  1618.         status = NetUltraLoad(statePtr, load.address, load.length,
  1619.                 ucodePtr);
  1620.         break;
  1621.     }
  1622.     case IOC_ULTRA_GO: {
  1623.         Dev_UltraGo            go;
  1624.         inSize = ioctlPtr->inBufSize;
  1625.         outSize = sizeof(go);
  1626.         fmtStatus = Fmt_Convert("{w1}", ioctlPtr->format, &inSize,
  1627.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1628.                 (Address) &go.address);
  1629.         if (fmtStatus != 0) {
  1630.         if (fmtStatus == FMT_INPUT_TOO_SMALL) {
  1631.             return GEN_INVALID_ARG;
  1632.         } else {
  1633.             printf("NetUltraIOControl: Fmt_Convert returned %d\n",
  1634.             fmtStatus);
  1635.             return FAILURE;
  1636.         }
  1637.         }
  1638.         status = NetUltraGo(statePtr, go.address);
  1639.         break;
  1640.     }
  1641.     case IOC_ULTRA_INIT: {
  1642.         status = NetUltraInitAdapter(statePtr);
  1643.         break;
  1644.     }
  1645.     case IOC_ULTRA_START: {
  1646.         MASTER_LOCK(&interPtr->mutex);
  1647.         status = NetUltraStart(statePtr);
  1648.         MASTER_UNLOCK(&interPtr->mutex);
  1649.         break;
  1650.     }
  1651.     case IOC_ULTRA_ADDRESS: {
  1652.         /* 
  1653.          * Set the adapter address.  This is not the normal way to
  1654.          * do this (usually happens during route installation) but
  1655.          * it is useful for debugging. 
  1656.          */
  1657.         Net_UltraAddress    address;
  1658.         int            group;
  1659.         int            unit;
  1660.         inSize = ioctlPtr->inBufSize;
  1661.         outSize = sizeof(Net_UltraAddress);
  1662.         fmtStatus = Fmt_Convert("{b8}", ioctlPtr->format, &inSize,
  1663.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1664.                 (Address) &address);
  1665.         if (fmtStatus != 0) {
  1666.         if (fmtStatus == FMT_INPUT_TOO_SMALL) {
  1667.             return GEN_INVALID_ARG;
  1668.         } else {
  1669.             printf("NetUltraIOControl: Fmt_Convert returned %d\n",
  1670.             fmtStatus);
  1671.             return FAILURE;
  1672.         }
  1673.         }
  1674.         Net_UltraAddressGet(&address, &group, &unit);
  1675.         printf("Setting ultra address to %d/%d\n", group, unit); 
  1676.         MASTER_LOCK(&interPtr->mutex);
  1677.         interPtr->netAddress[NET_PROTO_RAW].ultra = address;
  1678.         MASTER_UNLOCK(&interPtr->mutex);
  1679.         break;
  1680.     }
  1681.     case IOC_ULTRA_SEND_DGRAM: {
  1682.         Dev_UltraSendDgram        dgram;
  1683.         inSize = ioctlPtr->inBufSize;
  1684.         outSize = sizeof(dgram);
  1685.         fmtStatus = Fmt_Convert("{w2{w2}wb*}", ioctlPtr->format, &inSize,
  1686.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1687.                 (Address) &dgram);
  1688.         if (fmtStatus != 0) {
  1689.         if (fmtStatus == FMT_INPUT_TOO_SMALL) {
  1690.             return GEN_INVALID_ARG;
  1691.         } else {
  1692.             printf("NetUltraIOControl: Fmt_Convert returned %d\n",
  1693.             fmtStatus);
  1694.             return FAILURE;
  1695.         }
  1696.         }
  1697.         status = NetUltraSendDgram(interPtr, &dgram.address, dgram.count,
  1698.             dgram.size, 
  1699.             (dgram.useBuffer == TRUE) ? (Address) dgram.buffer :
  1700.             (Address) NIL, &dgram.time);
  1701.         inSize = sizeof(dgram);
  1702.         outSize = ioctlPtr->outBufSize;
  1703.         fmtStatus = Fmt_Convert("{w2{w2}wb*}", mach_Format, &inSize,
  1704.         (Address) &dgram, ioctlPtr->format, &outSize,
  1705.         (Address) ioctlPtr->outBuffer);
  1706.         if (fmtStatus != 0) {
  1707.         if (fmtStatus == FMT_OUTPUT_TOO_SMALL) {
  1708.             return GEN_INVALID_ARG;
  1709.         } else {
  1710.             printf(
  1711.             "NetUltraIOControl: Fmt_Convert returned %d\n",
  1712.             fmtStatus);
  1713.             return FAILURE;
  1714.         }
  1715.         }
  1716.         break;
  1717.     }
  1718.     case IOC_ULTRA_ECHO: {
  1719.         Dev_UltraEcho        echo;
  1720.         inSize = ioctlPtr->inBufSize;
  1721.         outSize = sizeof(echo);
  1722.         fmtStatus = Fmt_Convert("{w}", ioctlPtr->format, &inSize,
  1723.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1724.                 (Address) &echo);
  1725.         if (fmtStatus != 0) {
  1726.         if (fmtStatus == FMT_INPUT_TOO_SMALL) {
  1727.             return GEN_INVALID_ARG;
  1728.         } else {
  1729.             printf("NetUltraIOControl: Fmt_Convert returned %d\n",
  1730.             fmtStatus);
  1731.             return FAILURE;
  1732.         }
  1733.         }
  1734.         if (echo.echo == TRUE) {
  1735.         statePtr->flags |= NET_ULTRA_STATE_ECHO;
  1736.         statePtr->flags &= ~NET_ULTRA_STATE_NORMAL;
  1737.         } else {
  1738.         statePtr->flags &= ~NET_ULTRA_STATE_ECHO;
  1739.         statePtr->flags |= NET_ULTRA_STATE_NORMAL;
  1740.         }
  1741.         break;
  1742.     }
  1743.     case IOC_ULTRA_SOURCE: {
  1744.         Dev_UltraSendDgram        dgram;
  1745.         inSize = ioctlPtr->inBufSize;
  1746.         outSize = sizeof(dgram);
  1747.         fmtStatus = Fmt_Convert("{w2{w2}wb*}", ioctlPtr->format, &inSize,
  1748.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1749.                 (Address) &dgram);
  1750.         if (fmtStatus != 0) {
  1751.         if (fmtStatus == FMT_INPUT_TOO_SMALL) {
  1752.             return GEN_INVALID_ARG;
  1753.         } else {
  1754.             printf("NetUltraIOControl: Fmt_Convert returned %d\n",
  1755.             fmtStatus);
  1756.             return FAILURE;
  1757.         }
  1758.         }
  1759.         status = NetUltraSource(interPtr, &dgram.address, dgram.count,
  1760.             dgram.size, 
  1761.             (dgram.useBuffer == TRUE) ? (Address) dgram.buffer :
  1762.             (Address) NIL, &dgram.time);
  1763.         inSize = sizeof(dgram);
  1764.         outSize = ioctlPtr->outBufSize;
  1765.         fmtStatus = Fmt_Convert("{w2{w2}wb*}", mach_Format, &inSize,
  1766.         (Address) &dgram, ioctlPtr->format, &outSize,
  1767.         (Address) ioctlPtr->outBuffer);
  1768.         if (fmtStatus != 0) {
  1769.         if (fmtStatus == FMT_OUTPUT_TOO_SMALL) {
  1770.             return GEN_INVALID_ARG;
  1771.         } else {
  1772.             printf(
  1773.             "NetUltraIOControl: Fmt_Convert returned %d\n",
  1774.             fmtStatus);
  1775.             return FAILURE;
  1776.         }
  1777.         }
  1778.         break;
  1779.     }
  1780.     case IOC_ULTRA_SINK: {
  1781.         Dev_UltraSink        sink;
  1782.         int                value;
  1783.         outSize = sizeof(int);
  1784.         inSize = ioctlPtr->inBufSize;
  1785.         fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize,
  1786.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1787.                 (Address) &value);
  1788.         if (fmtStatus != 0) {
  1789.         printf("Format of IOC_ULTRA_TRACE parameter failed, 0x%x\n",
  1790.             fmtStatus);
  1791.         return GEN_INVALID_ARG;
  1792.         }
  1793.         outSize = ioctlPtr->outBufSize;
  1794.         sink.packets = packetsSunk;
  1795.         Timer_SubtractTicks(sinkEndTime, sinkStartTime, &sink.time);
  1796.         Timer_TicksToTime(sink.time, &sink.time);
  1797.         inSize = sizeof(sink);
  1798.         fmtStatus = Fmt_Convert("w{w2}", mach_Format, &inSize,
  1799.                 (Address) &sink, ioctlPtr->format, &outSize,
  1800.                 ioctlPtr->outBuffer);
  1801.         if (fmtStatus != 0) {
  1802.         printf("Format of IOC_ULTRA_TRACE parameter failed, 0x%x\n",
  1803.             fmtStatus);
  1804.         return GEN_INVALID_ARG;
  1805.         }
  1806.         if (value > 0) {
  1807.         statePtr->flags |= NET_ULTRA_STATE_SINK;
  1808.         statePtr->flags &= ~NET_ULTRA_STATE_NORMAL;
  1809.         packetsSunk = 0;
  1810.         } else {
  1811.         statePtr->flags &= ~NET_ULTRA_STATE_SINK;
  1812.         statePtr->flags |= NET_ULTRA_STATE_NORMAL;
  1813.         }
  1814.         break;
  1815.     }
  1816.     case IOC_ULTRA_COLLECT_STATS: {
  1817.         int        value;
  1818.         inSize = ioctlPtr->inBufSize;
  1819.         outSize = sizeof(int);
  1820.         fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize,
  1821.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1822.                 (Address) &value);
  1823.         if (fmtStatus != 0) {
  1824.         if (fmtStatus == FMT_INPUT_TOO_SMALL) {
  1825.             return GEN_INVALID_ARG;
  1826.         } else {
  1827.             printf("NetUltraIOControl: Fmt_Convert returned %d\n",
  1828.             fmtStatus);
  1829.             return FAILURE;
  1830.         }
  1831.         }
  1832.         if (value == TRUE) {
  1833.         statePtr->flags |= NET_ULTRA_STATE_STATS;
  1834.         } else {
  1835.         statePtr->flags &= ~NET_ULTRA_STATE_STATS;
  1836.         }
  1837.         break;
  1838.     }
  1839.     case IOC_ULTRA_CLEAR_STATS: {
  1840.         bzero((char *) &statePtr->stats, sizeof(statePtr->stats));
  1841.         break;
  1842.     }
  1843.     case IOC_ULTRA_GET_STATS: {
  1844.         outSize = ioctlPtr->outBufSize;
  1845.         inSize = sizeof(Dev_UltraStats);
  1846.         fmtStatus = Fmt_Convert("w*", mach_Format, &inSize,
  1847.                 (Address) &statePtr->stats, 
  1848.                 ioctlPtr->format, &outSize,
  1849.                 ioctlPtr->outBuffer);
  1850.         if (fmtStatus != 0) {
  1851.         printf("Format of IOC_ULTRA_GET_STATS parameter failed, 0x%x\n",
  1852.             fmtStatus);
  1853.         return GEN_INVALID_ARG;
  1854.         }
  1855.         break;
  1856.     }
  1857.     case IOC_ULTRA_MAP_THRESHOLD: {
  1858.         int                value;
  1859.         outSize = sizeof(int);
  1860.         inSize = ioctlPtr->inBufSize;
  1861.         fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize,
  1862.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1863.                 (Address) &value);
  1864.         if (fmtStatus != 0) {
  1865.         printf(
  1866.         "Format of IOC_ULTRA_MAP_THRESHOLD parameter failed, 0x%x\n",
  1867.             fmtStatus);
  1868.         return GEN_INVALID_ARG;
  1869.         }
  1870.         netUltraMapThreshold = value;
  1871.         break;
  1872.     }
  1873.     default: {
  1874.         printf("NetUltraIOControl: unknown ioctl 0x%x\n",
  1875.         ioctlPtr->command);
  1876.     }
  1877.  
  1878.     }
  1879.     return status;
  1880. }
  1881.  
  1882. /*
  1883.  *----------------------------------------------------------------------
  1884.  *
  1885.  * NetUltraSendReq --
  1886.  *
  1887.  *    Queue up a request for the adapter board. If there isn't
  1888.  *    any room in the queue then we block until there is.
  1889.  *
  1890.  * Results:
  1891.  *    Standard Sprite return status.
  1892.  *
  1893.  * Side effects:
  1894.  *    The adapter board is notified of the addition to the queue.
  1895.  *
  1896.  *----------------------------------------------------------------------
  1897.  */
  1898.  
  1899. ReturnStatus
  1900. NetUltraSendReq(statePtr, doneProc, data, rpc, scatterLength, scatterPtr, 
  1901.     requestSize, requestPtr)
  1902.     NetUltraState    *statePtr;    /* State of the adapter. */
  1903.     void        (*doneProc)();    /* Procedure to call when
  1904.                      * XRB is done. */
  1905.     ClientData        data;        /* Data used by doneProc. */
  1906.     Boolean        rpc;        /* Is this an RPC packet? */
  1907.     int            scatterLength;    /* Size of scatter/gather array. */
  1908.     Net_ScatterGather    *scatterPtr;    /* The scatter/gather array. */
  1909.     int            requestSize;    /* Size of the request. */
  1910.     NetUltraRequest    *requestPtr;    /* Request to be sent. */
  1911. {
  1912.     NetUltraXRB            *xrbPtr;
  1913.     NetUltraRequestHdr        *hdrPtr;
  1914.     NetUltraDMAInfo        *dmaPtr;
  1915.     ReturnStatus        status = SUCCESS;
  1916.     int                signal;
  1917.     NetUltraXRBInfo        *infoPtr;
  1918.     NetUltraTraceInfo        *tracePtr;
  1919.     int                size;
  1920.     int                i;
  1921.  
  1922.     if (netUltraDebug) {
  1923.     printf("NetUltraSendReq: sending a request\n");
  1924.     }
  1925.     xrbPtr = statePtr->nextToAdapterPtr;
  1926. #ifndef CLEAN
  1927.     if (netUltraTrace) {
  1928.     NEXT_TRACE(statePtr, &tracePtr);
  1929.     tracePtr->event = SEND_REQ;
  1930.     tracePtr->index = xrbPtr - statePtr->firstToAdapterPtr;
  1931.     Timer_GetCurrentTicks(&tracePtr->ticks);
  1932.     }
  1933. #endif
  1934.     if (statePtr->nextToAdapterPtr->filled) {
  1935. #ifndef CLEAN
  1936.     if (netUltraTrace) {
  1937.         NEXT_TRACE(statePtr, &tracePtr);
  1938.         tracePtr->event = TO_ADAPTER_FILLED;
  1939.         tracePtr->index = statePtr->nextToAdapterPtr - 
  1940.         statePtr->firstToAdapterPtr;
  1941.     }
  1942. #endif
  1943.     do {
  1944.         if (netUltraDebug) {
  1945.         printf("NetUltraSendReq: no XRB free, waiting\n");
  1946.         }
  1947.         statePtr->toAdapterAvail.waiting = TRUE;
  1948.         signal = Sync_SlowMasterWait(
  1949.             (unsigned int) &statePtr->toAdapterAvail,
  1950.             &statePtr->interPtr->mutex, TRUE);
  1951.         if (signal) {
  1952.         return GEN_ABORTED_BY_SIGNAL;
  1953.         }
  1954.     } while(statePtr->nextToAdapterPtr->filled);
  1955.     }
  1956.     xrbPtr = statePtr->nextToAdapterPtr;
  1957.     hdrPtr = (NetUltraRequestHdr *) requestPtr;
  1958.     infoPtr = (NetUltraXRBInfo *) List_First(statePtr->freeXRBInfoList);
  1959.     if ((List_Links *) infoPtr == statePtr->freeXRBInfoList) {
  1960.     panic("NetUltraSendReq: no available XRBInfo structures!");
  1961.     }
  1962.     List_Remove((List_Links *) infoPtr);
  1963.     List_Insert((List_Links *) infoPtr, 
  1964.     LIST_ATFRONT(statePtr->pendingXRBInfoList));
  1965.     infoPtr->doneProc = doneProc;
  1966.     infoPtr->doneData = data;
  1967.     infoPtr->xrbPtr = xrbPtr;
  1968.     infoPtr->scatterPtr = scatterPtr;
  1969.     infoPtr->scatterLength = scatterLength;
  1970.     infoPtr->requestSize = requestSize;
  1971.     infoPtr->requestPtr = (union NetUltraRequest *) requestPtr;
  1972.     infoPtr->flags = NET_ULTRA_INFO_PENDING;
  1973. #ifndef CLEAN
  1974.     if (netUltraDebug) {
  1975.     printf("NetUltraSendReq: using 0x%x\n", infoPtr);
  1976.     }
  1977. #endif
  1978. #ifndef CLEAN
  1979.     if (netUltraTrace) {
  1980.     NEXT_TRACE(statePtr, &tracePtr);
  1981.     tracePtr->event = SEND_REQ_INFO;
  1982.     tracePtr->index = xrbPtr - statePtr->firstToAdapterPtr;
  1983.     tracePtr->infoPtr = infoPtr;
  1984.     }
  1985. #endif
  1986.     hdrPtr->infoPtr = infoPtr;
  1987.     hdrPtr->status = 0;
  1988.     hdrPtr->reference = 0;
  1989.     if (scatterLength > 0) {
  1990.     Address        buffer;
  1991.     List_Links    *itemPtr;
  1992.     /*
  1993.      * If the buffer is not in DVMA space then get one that is.
  1994.      */
  1995.     if (! DVMA_ADDRESS(scatterPtr[0].bufAddr, statePtr)) {
  1996.         if (netUltraDebug) {
  1997.         printf("Data is not in DVMA space.\n");
  1998.         }
  1999.         while(List_IsEmpty(statePtr->freeBufferList)) {
  2000.         int        signal;
  2001.         statePtr->bufferAvail.waiting = TRUE;
  2002.         signal = Sync_SlowMasterWait(
  2003.             (unsigned int) &statePtr->bufferAvail,
  2004.             &statePtr->interPtr->mutex, TRUE);
  2005.         if (signal) {
  2006.             status = GEN_ABORTED_BY_SIGNAL;
  2007.             goto exit;
  2008.         }
  2009.         }
  2010.         itemPtr = List_First(statePtr->freeBufferList);
  2011.         if (itemPtr == statePtr->freeBufferList) {
  2012.         panic("NetUltraOutput: list screwup\n");
  2013.         }
  2014.         List_Remove(itemPtr);
  2015.         buffer = (Address) itemPtr;
  2016.         infoPtr->flags |= NET_ULTRA_INFO_STD_BUFFER;
  2017.         if (rpc) {
  2018.         int    lastIndex;
  2019.         /*
  2020.          * This is a standard RPC packet with 4 parts --
  2021.          * packet header, RPC header, RPC params, and data. 
  2022.          * Copy the first three into the DVMA buffer.  If the data
  2023.          * is below a threshold then copy it also.  Otherwise
  2024.          * map the data into DVMA space and remap the first three parts
  2025.          * so that they precede the data.
  2026.          */
  2027.         size = 0;
  2028.         lastIndex = scatterLength - 1;
  2029.         for (i = 0; i < scatterLength; i++) {
  2030.             size += scatterPtr[i].length;
  2031.         }
  2032.         if ((scatterPtr[lastIndex].length > 0) &&
  2033.             (((unsigned int) scatterPtr[lastIndex].bufAddr & 
  2034.             VMMACH_OFFSET_MASK_INT) + 
  2035.             scatterPtr[lastIndex].length > netUltraMapThreshold)) {
  2036.             Address            adjBuffer;
  2037.             Net_ScatterGather    tmpScatter[2];
  2038.             Net_ScatterGather    newScatter[2];
  2039.             int            junk;
  2040.             int            tmpSize;
  2041.             RpcHdrNew        *rpcHdrPtr;
  2042.  
  2043.             if (netUltraDebug) {
  2044.             printf("Mapping data into DVMA space.\n");
  2045.             }
  2046.             infoPtr->buffer = buffer;
  2047.             tmpSize = size - scatterPtr[lastIndex].length;
  2048.             adjBuffer = (Address) ((((unsigned int) (buffer + tmpSize) 
  2049.             & ~VMMACH_OFFSET_MASK_INT) + VMMACH_PAGE_SIZE_INT)
  2050.             - tmpSize);
  2051.             Net_GatherCopy(scatterPtr, lastIndex, adjBuffer);
  2052.             tmpScatter[0].bufAddr = adjBuffer;
  2053.             tmpScatter[0].length = tmpSize;
  2054.             tmpScatter[1] = scatterPtr[lastIndex];
  2055.             VmMach_DMAAllocContiguous(tmpScatter, 2, newScatter);
  2056.             buffer = newScatter[0].bufAddr;
  2057.             tmpSize = newScatter[1].bufAddr + newScatter[1].length - 
  2058.                 buffer;
  2059.             if (tmpSize > size + VMMACH_PAGE_SIZE_INT) {
  2060.             panic("Contiguous DVMA mapping failed.\n");
  2061.             }
  2062.             size = tmpSize;
  2063.             junk = (int) newScatter[1].bufAddr & VMMACH_OFFSET_MASK_INT;
  2064.             rpcHdrPtr = (RpcHdrNew *) buffer;
  2065.             rpcHdrPtr->dataStart += junk;
  2066.             infoPtr->flags |= NET_ULTRA_INFO_REMAP;
  2067.         } else {
  2068.             Net_GatherCopy(scatterPtr, scatterLength, buffer);
  2069.         }
  2070.         } else {
  2071.  
  2072.         if (netUltraDebug) {
  2073.             printf("Copying data into DVMA space.\n");
  2074.         }
  2075.         Net_GatherCopy(scatterPtr, 1, buffer);
  2076.         size = scatterPtr[0].length;
  2077.         }
  2078.     } else {
  2079.         /* 
  2080.          * The data is already in DVMA space.  It had better be contiguous!
  2081.          */
  2082.         if (netUltraDebug) {
  2083.         printf("Data is already in DVMA space.\n");
  2084.         }
  2085.         buffer = scatterPtr[0].bufAddr;
  2086.         size = scatterPtr[0].length;
  2087.     }
  2088.     if (! DVMA_ADDRESS(buffer, statePtr)) {
  2089.         buffer = BUFFER_TO_DVMA(buffer, statePtr);
  2090.     }
  2091.     hdrPtr->buffer = DVMA_TO_VME(buffer, statePtr);
  2092.     hdrPtr->size = size;
  2093.     } else {
  2094.     hdrPtr->size = 0;
  2095.     }
  2096.     if (netUltraDebug) {
  2097.     printf("NetUltraSendReq: hdrPtr->buffer = 0x%x, size = %d\n",
  2098.         hdrPtr->buffer, hdrPtr->size);
  2099.     }
  2100. #ifndef CLEAN
  2101.     if (statePtr->flags & NET_ULTRA_STATE_STATS) {
  2102.     if (hdrPtr->cmd == NET_ULTRA_DGRAM_SEND_REQ) {
  2103.         statePtr->stats.packetsSent++;
  2104.         statePtr->stats.bytesSent += hdrPtr->size;
  2105.         statePtr->stats.sentHistogram[hdrPtr->size >> 10]++;
  2106.     }
  2107.     }
  2108. #endif
  2109.     bcopy((char *) requestPtr, (char *) &xrbPtr->request, requestSize);
  2110.     dmaPtr = &xrbPtr->dma;
  2111.     if (hdrPtr->cmd == NET_ULTRA_DGRAM_SEND_REQ) {
  2112.     dmaPtr->cmd = NET_ULTRA_DMA_CMD_XRB_DATA;
  2113.     statePtr->numWritePending++;
  2114. #ifndef CLEAN
  2115.     if (netUltraDebug) {
  2116.         printf("NetUltraSendReq: number of pending writes = %d.\n",
  2117.         statePtr->numWritePending);
  2118.     }
  2119. #endif
  2120.     if (statePtr->numWritePending > statePtr->maxWritePending) {
  2121.         panic("NetUltraSendReq: too many writes.\n");
  2122.     }
  2123.     } else if (hdrPtr->cmd == NET_ULTRA_DGRAM_RECV_REQ) {
  2124.     dmaPtr->cmd = NET_ULTRA_DMA_CMD_XRB;
  2125.     statePtr->numReadPending++;
  2126. #ifndef CLEAN
  2127.     if (netUltraDebug) {
  2128.         printf("NetUltraSendReq: number of pending reads = %d.\n",
  2129.         statePtr->numReadPending);
  2130.     }
  2131. #endif
  2132.     if (statePtr->numReadPending > statePtr->maxReadPending) {
  2133.         panic("NetUltraSendReq: too many reads.\n");
  2134.     }
  2135.     } else {
  2136.     dmaPtr->cmd = NET_ULTRA_DMA_CMD_XRB;
  2137.     }
  2138.     dmaPtr->id = 0;
  2139.     dmaPtr->reference = 0;
  2140.     dmaPtr->offset = 0;
  2141.     dmaPtr->infoPtr = (NetUltraXRBInfo *) NIL;
  2142.     dmaPtr->length = requestSize;
  2143.     /*
  2144.      * Set the filled field so the adapter will process the XRB.
  2145.      */
  2146.     if (netUltraDebug) {
  2147.     printf("NetUltraSendReq: xrbPtr = 0x%x\n", xrbPtr);
  2148.     }
  2149.     xrbPtr->filled = 1;
  2150.     if (statePtr->nextToAdapterPtr == statePtr->lastToAdapterPtr) {
  2151.     statePtr->nextToAdapterPtr = statePtr->firstToAdapterPtr;
  2152.     } else {
  2153.     statePtr->nextToAdapterPtr++;
  2154.     }
  2155.     /*
  2156.      * Poke the adapter by setting the address register to 0. This
  2157.      * tells it to look in the queue.
  2158.      */
  2159.     *statePtr->intrReg = 0;
  2160. #ifndef CLEAN
  2161.     if (netUltraDebug) {
  2162.     printf("NetUltraSendReq: returning\n");
  2163.     }
  2164. #endif
  2165. exit:
  2166.     return status;
  2167. }
  2168.  
  2169. /*
  2170.  *----------------------------------------------------------------------
  2171.  *
  2172.  * GetStatusString --
  2173.  *
  2174.  *    Returns a string corresponding to the given status (status
  2175.  *    is a field in a NetUltraRequestHdr.
  2176.  *
  2177.  * Results:
  2178.  *    Ptr to string describing the status.
  2179.  *
  2180.  * Side effects:
  2181.  *    None.
  2182.  *
  2183.  *----------------------------------------------------------------------
  2184.  */
  2185.  
  2186. static char *
  2187. GetStatusString(status)
  2188.     unsigned char    status;
  2189. {
  2190.     static char *statusMsg[] = {
  2191.     "Unknown",                /* 0 */
  2192.     "OK",                    /* 1 */
  2193.     "FAIL: invalid request",        /* 2 */
  2194.     "OK: EOM",                /* 3 */
  2195.     "FAIL: no resources",            /* 4 */
  2196.     "OK: decide",                /* 5 */
  2197.     "FAIL: unknown reference",        /* 6 */
  2198.     "OK: closed",                /* 7 */
  2199.     "FAIL: buffer too small",        /* 8 */
  2200.     "OK; withdrawn",            /* 9 */
  2201.     "FAIL: buffer too large",        /* 10 */
  2202.     "OK: reject connection",        /* 11 */
  2203.     "FAIL: illegal request",        /* 12 */
  2204.     "OK: connection request",        /* 13 */
  2205.     "FAIL: REM abort",            /* 14 */
  2206.     "OK: closing",                /* 15 */
  2207.     "FAIL: LOC timeout",            /* 16 */
  2208.     "OK: timed-out",            /* 17 */
  2209.     "FAIL: unknown connection class",     /* 18 */
  2210.     "OK: out of sequence",            /* 19 */
  2211.     "FAIL: duplicate request",        /* 20 */
  2212.     "Unknown",                /* 21 */
  2213.     "FAIL: connection rejected",        /* 22 */
  2214.     "Unknown",                /* 23 */
  2215.     "FAIL: negotiation failed",        /* 24 */
  2216.     "Unknown",                /* 25 */
  2217.     "FAIL: illegal address",        /* 26 */
  2218.     "Unknown",                /* 27 */
  2219.     "FAIL: network error",            /* 28 */
  2220.     "Unknown",                /* 29 */
  2221.     "FAIL: protocol error",            /* 30 */
  2222.     "Unknown",                /* 31 */
  2223.     "FAIL: illegal RB length",        /* 32 */
  2224.     "Unknown",                /* 33 */
  2225.     "FAIL: unknown SAP id",            /* 34 */
  2226.     "Unknown",                /* 35 */
  2227.     "FAIL: zero RB id",            /* 36 */
  2228.     "Unknown",                /* 37 */
  2229.     "FAIL: adapter down",            /* 38 */
  2230.     };
  2231.     static int numStatusMsg = sizeof(statusMsg) / sizeof(char *);
  2232.  
  2233.     if (status >= numStatusMsg) {
  2234.     return "Unknown";
  2235.     } else {
  2236.     return statusMsg[status];
  2237.     }
  2238. }
  2239.  
  2240. /*
  2241.  *----------------------------------------------------------------------
  2242.  *
  2243.  * InitQueues --
  2244.  *
  2245.  *    Initializes the XRB queues.
  2246.  *
  2247.  * Results:
  2248.  *    None.
  2249.  *
  2250.  * Side effects:
  2251.  *    Memory is allocated and mapped into DMA space if necessary.
  2252.  *
  2253.  *----------------------------------------------------------------------
  2254.  */
  2255.  
  2256. static void
  2257. InitQueues(statePtr)
  2258.     NetUltraState    *statePtr;    /* State of the adapter. */
  2259. {
  2260.     int        size;
  2261.     Address    addr;
  2262.     List_Links    *itemPtr;
  2263.     int        i;
  2264.  
  2265.     if (!(statePtr->queuesInit)) {
  2266.     /*
  2267.      * Allocate XRBs that go from the adapter to the host. 
  2268.      */
  2269.     size = sizeof(NetUltraXRB) * NET_ULTRA_NUM_TO_HOST;
  2270.     addr = (Address) malloc(size);
  2271.     addr = VmMach_DMAAlloc(size, (Address) addr);
  2272.     if (addr == (Address) NIL) {
  2273.         panic("NetUltraInit: unable to allocate DMA space.\n");
  2274.     }
  2275.     statePtr->firstToHostPtr = (NetUltraXRB *) addr;
  2276.     /* 
  2277.      * Allocate XRBs that go from the host to the adapter. 
  2278.      */
  2279.     size = sizeof(NetUltraXRB) * NET_ULTRA_NUM_TO_ADAPTER;
  2280.     addr = (Address) malloc(size);
  2281.     addr = VmMach_DMAAlloc(size, (Address) addr);
  2282.     if (addr == (Address) NIL) {
  2283.         panic("NetUltraInit: unable to allocate DMA space.\n");
  2284.     }
  2285.     statePtr->firstToAdapterPtr = (NetUltraXRB *) addr;
  2286.     statePtr->pendingXRBInfoList = &statePtr->pendingXRBInfoListHdr;
  2287.     statePtr->freeXRBInfoList = &statePtr->freeXRBInfoListHdr;
  2288.     List_Init(statePtr->pendingXRBInfoList);
  2289.     List_Init(statePtr->freeXRBInfoList);
  2290.     for (i = 0; i < NET_ULTRA_NUM_TO_ADAPTER + NET_ULTRA_NUM_TO_HOST; i++) {
  2291.         itemPtr = (List_Links *) malloc(sizeof(NetUltraXRBInfo));
  2292.         List_InitElement(itemPtr);
  2293.         List_Insert(itemPtr, LIST_ATREAR(statePtr->freeXRBInfoList));
  2294.     }
  2295.     /*
  2296.      * Allocate buffers in DVMA space for pending reads and writes. 
  2297.      */
  2298.     statePtr->maxReadPending = NET_ULTRA_PENDING_READS;
  2299.     statePtr->numReadPending = 0;
  2300.     statePtr->maxWritePending = NET_ULTRA_PENDING_WRITES;
  2301.     statePtr->numWritePending = 0;
  2302.     statePtr->numBuffers = statePtr->maxReadPending + 
  2303.         statePtr->maxWritePending;
  2304.     statePtr->bufferSize = NET_ULTRA_MAX_BYTES;
  2305.     size = statePtr->numBuffers * statePtr->bufferSize;
  2306.     addr = (Address) malloc(size);
  2307.     statePtr->buffers = addr;
  2308.     addr = VmMach_DMAAlloc(size, (Address) addr);
  2309.     statePtr->buffersDVMA = addr;
  2310.     statePtr->freeBufferList = &statePtr->freeBufferListHdr;
  2311.  
  2312.     statePtr->queuesInit = TRUE;
  2313.     }
  2314.     statePtr->lastToHostPtr = statePtr->firstToHostPtr + 
  2315.         NET_ULTRA_NUM_TO_HOST - 1;
  2316.     statePtr->nextToHostPtr = statePtr->firstToHostPtr;
  2317.     statePtr->lastToAdapterPtr = statePtr->firstToAdapterPtr + 
  2318.         NET_ULTRA_NUM_TO_ADAPTER - 1;
  2319.     statePtr->nextToAdapterPtr = statePtr->firstToAdapterPtr;
  2320.     size = sizeof(NetUltraXRB) * NET_ULTRA_NUM_TO_HOST;
  2321.     bzero((char *) statePtr->firstToHostPtr, size);
  2322.     size = sizeof(NetUltraXRB) * NET_ULTRA_NUM_TO_ADAPTER;
  2323.     bzero((char *) statePtr->firstToAdapterPtr, size);
  2324.     while (!List_IsEmpty(statePtr->pendingXRBInfoList)) {
  2325.     itemPtr = List_First(statePtr->pendingXRBInfoList);
  2326.     List_Remove(itemPtr);
  2327.     List_Insert(itemPtr, LIST_ATREAR(statePtr->freeXRBInfoList));
  2328.     }
  2329.     bzero((char *) statePtr->buffers, statePtr->numBuffers * 
  2330.     statePtr->bufferSize);
  2331.     List_Init(statePtr->freeBufferList);
  2332.     for (i = 0; i < statePtr->numBuffers; i++) {
  2333.     itemPtr = (List_Links *) 
  2334.         (statePtr->buffers + (i * statePtr->bufferSize));
  2335.     List_InitElement(itemPtr);
  2336.     List_Insert(itemPtr, LIST_ATREAR(statePtr->freeBufferList));
  2337.     }
  2338. }
  2339.  
  2340. /*
  2341.  *----------------------------------------------------------------------
  2342.  *
  2343.  * NetUltraPendingRead --
  2344.  *
  2345.  *    Send a pending read to the adapter.
  2346.  *
  2347.  * Results:
  2348.  *    Standard Sprite return status.
  2349.  *
  2350.  * Side effects:
  2351.  *    A "read datagram" XRB is sent to the adapter.
  2352.  *
  2353.  *----------------------------------------------------------------------
  2354.  */
  2355.  
  2356. ReturnStatus
  2357. NetUltraPendingRead(interPtr, size, buffer)
  2358.     Net_Interface    *interPtr;    /* Interface to read from. */
  2359.     int            size;        /* Size of the data buffer. */
  2360.     Address        buffer;        /* Address of the buffer in DMA space */
  2361. {
  2362.     NetUltraState        *statePtr;
  2363.     NetUltraRequest        request;
  2364.     NetUltraDatagramRequest    *dgramReqPtr;
  2365.     NetUltraRequestHdr        *hdrPtr;
  2366.     ReturnStatus        status = SUCCESS;
  2367.     Net_ScatterGather        scatter;
  2368.  
  2369.     statePtr = (NetUltraState *) interPtr->interfaceData;
  2370.     if (!(statePtr->flags & NET_ULTRA_STATE_START)) {
  2371.     printf("NetUltraPendingRead: adapter not started!\n");
  2372.     return FAILURE;
  2373.     }
  2374. #ifndef CLEAN
  2375.     if (netUltraDebug) {
  2376.     printf("NetUltraPendingRead: queuing a pending read.\n");
  2377.     printf("Buffer size = %d, buffer = 0x%x\n", size, buffer);
  2378.     }
  2379. #endif
  2380.     statePtr = (NetUltraState *) interPtr->interfaceData;
  2381.     bzero((char *) &request, sizeof(request));
  2382.     dgramReqPtr = &request.dgram;
  2383.     hdrPtr = &dgramReqPtr->hdr;
  2384.     dgramReqPtr->remoteAddress = wildcardAddress;
  2385.     dgramReqPtr->localAddress = wildcardAddress;
  2386.     hdrPtr->cmd = NET_ULTRA_DGRAM_RECV_REQ;
  2387.     /*
  2388.      * Save room at the beginning of the buffer for the datagram request
  2389.      * block.  The higher-level software expects the packet header to
  2390.      * proceed the packet (this should be fixed sometime).
  2391.      */
  2392.     buffer += sizeof(NetUltraDatagramRequest);
  2393.     size -= sizeof(NetUltraDatagramRequest);
  2394.     scatter.bufAddr = buffer;
  2395.     scatter.length = size;
  2396.     status = NetUltraSendReq(statePtr, ReadDone, (ClientData) 0, FALSE,  
  2397.     1, &scatter, sizeof(NetUltraDatagramRequest), &request);
  2398.     if (status != SUCCESS) {
  2399.     printf("NetUltraPendingRead: could not send request to adapter\n");
  2400.     }
  2401. #ifndef CLEAN
  2402.     if (netUltraDebug) {
  2403.     printf("NetUltraPendingRead: returning.\n");
  2404.     }
  2405. #endif
  2406.     return status;
  2407. }
  2408.  
  2409. /*
  2410.  *----------------------------------------------------------------------
  2411.  *
  2412.  * ReadDone --
  2413.  *
  2414.  *    This routine is called from the interrupt handler when a read
  2415.  *    request completes.
  2416.  *
  2417.  * Results:
  2418.  *    None.
  2419.  *
  2420.  * Side effects:
  2421.  *    None.
  2422.  *
  2423.  *----------------------------------------------------------------------
  2424.  */
  2425.  
  2426. static void
  2427. ReadDone(interPtr, infoPtr)
  2428.     Net_Interface    *interPtr;    /* Interface. */
  2429.     NetUltraXRBInfo    *infoPtr;    /* Info about XRB that completed. */
  2430. {
  2431.     NetUltraXRB            *xrbPtr;
  2432.     NetUltraDatagramRequest    *reqPtr;
  2433.     NetUltraRequestHdr        *hdrPtr;
  2434.     NetUltraState        *statePtr;
  2435.     int                size;
  2436.     Address            buffer = (Address) NIL;
  2437.     ReturnStatus        status = SUCCESS;
  2438.  
  2439.     xrbPtr = infoPtr->xrbPtr;
  2440.     reqPtr = &xrbPtr->request.dgram;
  2441.     hdrPtr = &reqPtr->hdr;
  2442.  
  2443.     statePtr = (NetUltraState *) interPtr->interfaceData;
  2444.     if (!(hdrPtr->status & NET_ULTRA_STATUS_OK)) {
  2445.     panic("ReadDone: read failed 0x%x (continuable)\n", hdrPtr->status);
  2446.     } else {
  2447. #ifndef CLEAN
  2448.     if (netUltraDebug) {
  2449.         char    local[32];
  2450.         char    remote[32];
  2451.         printf("ReadDone: received a packet.\n");
  2452.         *local = '\0';
  2453.         *remote = '\0';
  2454.         (void) Net_AddrToString((Net_Address *) 
  2455.             &reqPtr->localAddress.address, 
  2456.             NET_PROTO_RAW, NET_NETWORK_ULTRA, local);
  2457.         (void) Net_AddrToString((Net_Address *) 
  2458.             &reqPtr->remoteAddress.address, 
  2459.             NET_PROTO_RAW, NET_NETWORK_ULTRA, remote);
  2460.         printf("Local address: %s\n", local);
  2461.         printf("Remote address: %s\n", remote);
  2462.         printf("Data size = %d\n", hdrPtr->size);
  2463.         if (hdrPtr->size > 0) {
  2464.         printf("Data: %s\n", hdrPtr->buffer + VMMACH_DMA_START_ADDR);
  2465.         }
  2466.     }
  2467. #endif
  2468.     /*
  2469.      * Adjust size and start of buffer to account for the space
  2470.      * for the request block.
  2471.      */
  2472.     buffer = VME_TO_BUFFER(hdrPtr->buffer, statePtr) -
  2473.             sizeof(NetUltraDatagramRequest);
  2474.     size = hdrPtr->size + sizeof(NetUltraDatagramRequest);
  2475.     if (statePtr->flags & NET_ULTRA_STATE_NORMAL) {
  2476.         /* 
  2477.          * Copy the request block (packet header) to the start of the
  2478.          * packet. 
  2479.          */
  2480.  
  2481.         *((NetUltraDatagramRequest *) buffer) = *reqPtr;
  2482.         /*
  2483.          * Release the lock around interface so that the RPC system
  2484.          * can output a packet in response to this one.  The XRB is
  2485.          * still marked as filled, so the adapter won't overwrite it.
  2486.          * Also the XRBinfo is not marked as pending, so the interrupt
  2487.          * routine won't re-process the packet should it loop around
  2488.          * the queue before Net_Input returns.
  2489.          */
  2490.         MASTER_UNLOCK(&interPtr->mutex);
  2491.         Net_Input(interPtr, buffer, size);
  2492.         MASTER_LOCK(&interPtr->mutex);
  2493.     } else if (statePtr->flags & NET_ULTRA_STATE_ECHO) {
  2494.         Net_ScatterGather        tmpScatter;
  2495.         if (netUltraDebug) {
  2496.         printf("ReadDone: returning datagram to sender.\n");
  2497.         }
  2498.         hdrPtr->cmd = NET_ULTRA_DGRAM_SEND_REQ;
  2499.         hdrPtr->status = 0;
  2500.         tmpScatter.bufAddr = BUFFER_TO_DVMA(buffer, statePtr);
  2501.         tmpScatter.length = hdrPtr->size;
  2502.         status = NetUltraSendReq(statePtr, EchoDone, (ClientData) NIL, 
  2503.             FALSE, 1, &tmpScatter,sizeof(NetUltraDatagramRequest),
  2504.             (NetUltraRequest *) reqPtr);
  2505.         if (status != SUCCESS) {
  2506.         panic("ReadDone: unable to return datagram to sender.\n");
  2507.         }
  2508.     } else if (statePtr->flags & NET_ULTRA_STATE_DSND_TEST) {
  2509.         Net_ScatterGather        tmpScatter;
  2510.         dsndCount--;
  2511.         if (dsndCount > 0) {
  2512.         if (netUltraDebug) {
  2513.             printf("ReadDone: returning datagram to sender.\n");
  2514.         }
  2515.         hdrPtr->cmd = NET_ULTRA_DGRAM_SEND_REQ;
  2516.         hdrPtr->status = 0;
  2517.         tmpScatter.bufAddr = BUFFER_TO_DVMA(buffer, statePtr);
  2518.         tmpScatter.length = hdrPtr->size;
  2519.         status = NetUltraSendReq(statePtr, EchoDone, (ClientData) NIL, 
  2520.                 FALSE, 1, &tmpScatter,
  2521.                 sizeof(NetUltraDatagramRequest),
  2522.                 (NetUltraRequest *) reqPtr);
  2523.         if (status != SUCCESS) {
  2524.             panic("ReadDone: unable to return datagram to sender.\n");
  2525.         }
  2526.         } else {
  2527.  
  2528.         /*
  2529.          * Notify the waiting process that the last datagram has
  2530.          * arrived.
  2531.          */
  2532.         Sync_Broadcast(&dsndTestDone);
  2533.         }
  2534.     } else if (statePtr->flags & NET_ULTRA_STATE_SINK) {
  2535.         packetsSunk++;
  2536.     }
  2537.     }
  2538.     statePtr->numReadPending--;
  2539.     if (statePtr->numReadPending < 0) {
  2540.     panic("ReadDone: number of pending reads < 0.\n");
  2541.     }
  2542.     /* 
  2543.      * This may introduce a deadlock if the queues are of size 1, 
  2544.      * since the XRB and info structures are
  2545.      * not freed until this routine (ReadDone) returns, and 
  2546.      * NetUltraPendingRead needs to use these structures.  If the queues
  2547.      * are greater than 1 then NetUltraPendingRead may have to
  2548.      * wait for an XRB to free up, but that should be ok.
  2549.      */
  2550.     status = NetUltraPendingRead(interPtr, statePtr->bufferSize, 
  2551.         BUFFER_TO_DVMA(buffer,statePtr));
  2552.     if (status != SUCCESS) {
  2553.     printf("ReadDone: could not queue next pending read.\n");
  2554.     }
  2555. #ifndef CLEAN
  2556.     if (netUltraDebug) {
  2557.     printf("ReadDone: returning.\n");
  2558.     }
  2559. #endif
  2560. }
  2561.  
  2562. /*
  2563.  *----------------------------------------------------------------------
  2564.  *
  2565.  * EchoDone --
  2566.  *
  2567.  *    This routine is called when the write of a datagram that is
  2568.  *    being echoed back to the sender completes.  All it does is
  2569.  *    decrement the number of pending writes.
  2570.  *
  2571.  * Results:
  2572.  *    None.
  2573.  *
  2574.  * Side effects:
  2575.  *    None.
  2576.  *
  2577.  *----------------------------------------------------------------------
  2578.  */
  2579.  
  2580. /*ARGSUSED*/
  2581. static void
  2582. EchoDone(interPtr, infoPtr)
  2583.     Net_Interface    *interPtr;    /* Interface. */
  2584.     NetUltraXRBInfo    *infoPtr;    /* Info about XRB that completed. */
  2585. {
  2586.     NetUltraState    *statePtr;
  2587.  
  2588.     statePtr = (NetUltraState *) interPtr->interfaceData;
  2589.     statePtr->numWritePending--;
  2590. }
  2591.  
  2592.  
  2593. /*
  2594.  *----------------------------------------------------------------------
  2595.  *
  2596.  * NetUltraSendDgram --
  2597.  *
  2598.  *    This routine will send a datagram to the specified host.  It
  2599.  *    is intended for debugging purposes.  
  2600.  *
  2601.  * Results:
  2602.  *    None.
  2603.  *
  2604.  * Side effects:
  2605.  *    A write is queued to the adapter.
  2606.  *
  2607.  *----------------------------------------------------------------------
  2608.  */
  2609.  
  2610. static ReturnStatus
  2611. NetUltraSendDgram(interPtr, netAddressPtr, count, bufSize, buffer, timePtr)
  2612.     Net_Interface    *interPtr;        /* Interface to send on. */
  2613.     Net_Address        *netAddressPtr;        /* Host to send to. */
  2614.     int            count;            /* Number of times to send
  2615.                          * datagram. */
  2616.     int            bufSize;        /* Size of data buffer. */
  2617.     Address        buffer;            /* Data to send. */
  2618.     Time        *timePtr;        /* Place to store total 
  2619.                          * time to send datagrams. */
  2620. {
  2621.     NetUltraState        *statePtr;
  2622.     NetUltraRequest        request;
  2623.     NetUltraDatagramRequest    *dgramReqPtr;
  2624.     NetUltraRequestHdr        *hdrPtr;
  2625.     ReturnStatus        status;
  2626.     Net_Address            *addressPtr;
  2627.     Timer_Ticks         startTime;
  2628.     Timer_Ticks         endTime;
  2629.     Timer_Ticks         curTime;
  2630.     NetUltraTraceInfo        *tracePtr;
  2631.     Net_ScatterGather        scatter;
  2632.  
  2633.     MASTER_LOCK(&interPtr->mutex);
  2634. #ifndef CLEAN
  2635.     if (netUltraDebug) {
  2636.     char    address[100];
  2637.     (void) Net_AddrToString(netAddressPtr, NET_PROTO_RAW, NET_NETWORK_ULTRA,
  2638.             address);
  2639.     printf("NetUltraSendDgram: sending to %s\n", address);
  2640.     }
  2641. #endif
  2642.     statePtr = (NetUltraState *) interPtr->interfaceData;
  2643.     if (!(statePtr->flags & NET_ULTRA_STATE_START)) {
  2644.     printf("NetUltraSendDgram: adapter not started!\n");
  2645.     status = FAILURE;
  2646.     goto exit;
  2647.     }
  2648.     bzero((char *) &request, sizeof(request));
  2649.     dgramReqPtr = &request.dgram;
  2650.     hdrPtr = &dgramReqPtr->hdr;
  2651.     dgramReqPtr->remoteAddress = wildcardAddress;
  2652.     dgramReqPtr->remoteAddress.tsapSize = 2;
  2653.     dgramReqPtr->remoteAddress.tsap[1] = 1;
  2654.     dgramReqPtr->remoteAddress.address = netAddressPtr->ultra;
  2655.     addressPtr = (Net_Address *) &dgramReqPtr->remoteAddress.address;
  2656.     addressPtr->generic.data[1] = 0x49;
  2657.     addressPtr->generic.data[6] = 0xfe;
  2658.     dgramReqPtr->localAddress = wildcardAddress;
  2659.     dgramReqPtr->localAddress.tsapSize = 2;
  2660.     dgramReqPtr->localAddress.tsap[1] = 1;
  2661.     dgramReqPtr->localAddress.address = 
  2662.     interPtr->netAddress[NET_PROTO_RAW].ultra;
  2663.     addressPtr = (Net_Address *) &dgramReqPtr->localAddress.address;
  2664.     addressPtr->generic.data[1] = 0x49;
  2665.     addressPtr->generic.data[6] = 0xfe;
  2666.     hdrPtr->cmd = NET_ULTRA_DGRAM_SEND_REQ;
  2667.     scatter.bufAddr = buffer;
  2668.     scatter.length = bufSize;
  2669.     statePtr->flags |= NET_ULTRA_STATE_DSND_TEST;
  2670.     statePtr->flags &= ~NET_ULTRA_STATE_NORMAL;
  2671.     dsndCount = count;
  2672. #ifndef CLEAN
  2673.     if (netUltraTrace) {
  2674.     NEXT_TRACE(statePtr, &tracePtr);
  2675.     tracePtr->event = DSND;
  2676.     Timer_GetCurrentTicks(&curTime);
  2677.     tracePtr->ticks = curTime;
  2678.     }
  2679. #endif
  2680.     Timer_GetCurrentTicks(&startTime);
  2681.     status = NetUltraSendReq(statePtr, DgramSendDone, (ClientData) NIL,
  2682.         FALSE, 1, &scatter, sizeof(NetUltraDatagramRequest), &request);
  2683.     Sync_MasterWait(&(dsndTestDone), &(interPtr->mutex), FALSE);
  2684.     Timer_GetCurrentTicks(&endTime);
  2685. #ifndef CLEAN
  2686.     if (netUltraDebug) {
  2687.     printf("NetUltraSendDgram: test done.\n");
  2688.     } 
  2689. #endif
  2690.     statePtr->flags &= ~NET_ULTRA_STATE_DSND_TEST;
  2691.     statePtr->flags |= NET_ULTRA_STATE_NORMAL;
  2692.     Timer_SubtractTicks(endTime, startTime, &endTime);
  2693.     Timer_TicksToTime(endTime, timePtr);
  2694. exit:
  2695.     MASTER_UNLOCK(&interPtr->mutex);
  2696.     return status;
  2697. }
  2698.  
  2699. /*
  2700.  *----------------------------------------------------------------------
  2701.  *
  2702.  * DgramSendDone --
  2703.  *
  2704.  *    Called by the interrupt handler when the datagram sent by 
  2705.  *     NetUltraSendDgram is actually sent.
  2706.  *
  2707.  * Results:
  2708.  *    None.
  2709.  *
  2710.  * Side effects:
  2711.  *    The process waiting for the datagram to be sent is notified.
  2712.  *
  2713.  *----------------------------------------------------------------------
  2714.  */
  2715.  
  2716. static void
  2717. DgramSendDone(interPtr, infoPtr)
  2718.     Net_Interface    *interPtr;    /* Interface. */
  2719.     NetUltraXRBInfo    *infoPtr;    /* Info about XRB that completed. */
  2720. {
  2721.     NetUltraXRB            *xrbPtr;
  2722.     NetUltraDatagramRequest    *reqPtr;
  2723.     NetUltraRequestHdr        *hdrPtr;
  2724.  
  2725.     xrbPtr = infoPtr->xrbPtr;
  2726.     reqPtr = &xrbPtr->request.dgram;
  2727.     hdrPtr = &reqPtr->hdr;
  2728.  
  2729.     if (!(hdrPtr->status & NET_ULTRA_STATUS_OK)) {
  2730.     panic("DgramSendDone: dgram send failed 0x%x\n", hdrPtr->status);
  2731.     } else {
  2732. #ifndef CLEAN
  2733.     if (netUltraDebug) {
  2734.         printf("DgramSendDone: datagram sent ok\n");
  2735.     }
  2736. #endif
  2737.     }
  2738.     ((NetUltraState *) interPtr->interfaceData)->numWritePending--;
  2739.     if (((NetUltraState *) interPtr->interfaceData)->numWritePending < 0) {
  2740.     panic("DgramSendDone: number of pending writes < 0.\n");
  2741.     }
  2742.     if (infoPtr->doneData != (ClientData) NIL) {
  2743.     Sync_Broadcast((Sync_Condition *) infoPtr->doneData);
  2744.     }
  2745. #ifndef CLEAN
  2746.     if (netUltraDebug) {
  2747.     printf("DgramSendDone: returning.\n");
  2748.     }
  2749. #endif
  2750.  
  2751. }
  2752.  
  2753.  
  2754. /*
  2755.  *----------------------------------------------------------------------
  2756.  *
  2757.  * NetUltraOutput --
  2758.  *
  2759.  *    Puts the outgoing packet into the queue to the adapter.
  2760.  *    Since the ultranet adapter does not to scatter/gather
  2761.  *    we have to get a free write buffer and copy the data
  2762.  *    into the buffer.
  2763.  *
  2764.  * Results:
  2765.  *    None.
  2766.  *
  2767.  * Side effects:
  2768.  *    The packet is put into the queue and the adapter is notified.
  2769.  *
  2770.  *----------------------------------------------------------------------
  2771.  */
  2772.  
  2773. ReturnStatus
  2774. NetUltraOutput(interPtr, hdrPtr, scatterGatherPtr, scatterGatherLength, rpc,
  2775.         statusPtr)
  2776.     Net_Interface        *interPtr;    /* The interface to use. */
  2777.     Address            hdrPtr;        /* Packet header. */
  2778.     Net_ScatterGather        *scatterGatherPtr; /* Scatter/gather elements.*/
  2779.     int                scatterGatherLength; /* Number of elements in
  2780.                               * scatter/gather list. */
  2781.     Boolean            rpc;        /* Is this an RPC packet? */
  2782.     ReturnStatus        *statusPtr;    /* Place to store status. */
  2783. {
  2784.     NetUltraState        *statePtr;
  2785.     ReturnStatus        status = SUCCESS;
  2786.     Net_UltraHeader        *ultraHdrPtr = (Net_UltraHeader *) hdrPtr;
  2787.  
  2788.     statePtr = (NetUltraState *) interPtr->interfaceData;
  2789.     if ((ultraHdrPtr->cmd != NET_ULTRA_DGRAM_SEND_REQ) && 
  2790.     (ultraHdrPtr->cmd != 0)) {
  2791.     printf("Invalid header to NetUltraOutput.\n");
  2792.     return FAILURE;
  2793.     }
  2794.     /*
  2795.      * If the cmd is 0 then the packet is from the network device.
  2796.      */
  2797.     if (ultraHdrPtr->cmd == 0) {
  2798.     ultraHdrPtr->cmd = NET_ULTRA_DGRAM_SEND_REQ;
  2799.     }
  2800.     MASTER_LOCK(&interPtr->mutex);
  2801.     if (netUltraDebug) {
  2802.     char    address[100];
  2803.     (void) Net_AddrToString((Net_Address *) 
  2804.         &ultraHdrPtr->remoteAddress.address, 
  2805.         NET_PROTO_RAW, NET_NETWORK_ULTRA,
  2806.             address);
  2807.     printf("NetUltraOutput: sending to %s\n", address);
  2808.     }
  2809.     status = NetUltraSendReq(statePtr, OutputDone, 
  2810.         (ClientData) statusPtr, rpc, scatterGatherLength, 
  2811.         scatterGatherPtr, sizeof(Net_UltraHeader), 
  2812.         (NetUltraRequest *) ultraHdrPtr);
  2813.     if (status != SUCCESS) {
  2814.     printf("NetUltraOutput: packet not sent\n");
  2815.     }
  2816.     MASTER_UNLOCK(&interPtr->mutex);
  2817.     return status;
  2818. }
  2819.  
  2820. /*
  2821.  *----------------------------------------------------------------------
  2822.  *
  2823.  * OutputDone --
  2824.  *
  2825.  *    This routine is called by the interrupt handler when a packet
  2826.  *    sent by NetUltraOutput completes.
  2827.  *
  2828.  * Results:
  2829.  *    None.
  2830.  *
  2831.  * Side effects:
  2832.  *    The write buffer associated with the command is added to
  2833.  *     the list of free write buffers.
  2834.  *
  2835.  *----------------------------------------------------------------------
  2836.  */
  2837.  
  2838. static void
  2839. OutputDone(interPtr, infoPtr)
  2840.     Net_Interface    *interPtr;    /* Interface. */
  2841.     NetUltraXRBInfo    *infoPtr;    /* Info about XRB that completed. */
  2842. {
  2843.     NetUltraRequestHdr        *hdrPtr;
  2844.     NetUltraState        *statePtr;
  2845.     ReturnStatus        *statusPtr;
  2846.     ReturnStatus        status = SUCCESS;
  2847.  
  2848.     hdrPtr = &(infoPtr->xrbPtr->request.dgram.hdr);
  2849.     statusPtr = (ReturnStatus *) infoPtr->doneData;
  2850.  
  2851.     statePtr = (NetUltraState *) interPtr->interfaceData;
  2852.     if (!(hdrPtr->status & NET_ULTRA_STATUS_OK)) {
  2853.     printf("Warning: OutputDone: write failed 0x%x\n", hdrPtr->status);
  2854.     status = FAILURE;
  2855.     } 
  2856. #ifndef CLEAN
  2857.     if (netUltraDebug) {
  2858.     printf("OutputDone: packet sent\n");
  2859.     }
  2860. #endif
  2861.     statePtr->numWritePending--;
  2862.     if (statePtr->numWritePending < 0) {
  2863.     panic("OutputDone: number of pending writes < 0.\n");
  2864.     }
  2865.     /*
  2866.      * Return status to the waiting process.
  2867.      */
  2868.     if (statusPtr != (ReturnStatus *) NIL) {
  2869.     *statusPtr = status;
  2870.     }
  2871.     /*
  2872.      * Wakeup any process waiting for the packet to be sent.
  2873.      */
  2874.     infoPtr->scatterPtr->done = TRUE;
  2875.     if (infoPtr->scatterPtr->mutexPtr != (Sync_Semaphore *) NIL) {
  2876.     NetOutputWakeup(infoPtr->scatterPtr->mutexPtr);
  2877.     }
  2878. }
  2879.  
  2880. /*
  2881.  *----------------------------------------------------------------------
  2882.  *
  2883.  * NetUltraSource --
  2884.  *
  2885.  *    This routine will send a stream of datagrams to the specified host.
  2886.  *
  2887.  * Results:
  2888.  *    None.
  2889.  *
  2890.  * Side effects:
  2891.  *    A write is queued to the adapter.
  2892.  *
  2893.  *----------------------------------------------------------------------
  2894.  */
  2895.  
  2896. static ReturnStatus
  2897. NetUltraSource(interPtr, netAddressPtr, count, bufSize, buffer, timePtr)
  2898.     Net_Interface    *interPtr;        /* Interface to send on. */
  2899.     Net_Address        *netAddressPtr;        /* Host to send to. */
  2900.     int            count;            /* Number of times to send
  2901.                          * datagram. */
  2902.     int            bufSize;        /* Size of data buffer. */
  2903.     Address        buffer;            /* Data to send. */
  2904.     Time        *timePtr;        /* Place to store total 
  2905.                          * time to send datagrams. */
  2906. {
  2907.     NetUltraState        *statePtr;
  2908.     NetUltraRequest        request;
  2909.     NetUltraDatagramRequest    *dgramReqPtr;
  2910.     NetUltraRequestHdr        *hdrPtr;
  2911.     ReturnStatus        status = SUCCESS;
  2912.     List_Links            *itemPtr;
  2913.     Net_Address            *addressPtr;
  2914.     Timer_Ticks         startTime;
  2915.     Timer_Ticks         endTime;
  2916.     Timer_Ticks         curTime;
  2917.     NetUltraTraceInfo        *tracePtr;
  2918.     Net_ScatterGather        scatter;
  2919.  
  2920.     MASTER_LOCK(&interPtr->mutex);
  2921. #ifndef CLEAN
  2922.     if (netUltraDebug) {
  2923.     char    address[100];
  2924.     (void) Net_AddrToString(netAddressPtr, NET_PROTO_RAW, NET_NETWORK_ULTRA,
  2925.             address);
  2926.     printf("NetUltraSendDgram: sending to %s\n", address);
  2927.     }
  2928. #endif
  2929.     statePtr = (NetUltraState *) interPtr->interfaceData;
  2930.     if (!(statePtr->flags & NET_ULTRA_STATE_START)) {
  2931.     printf("NetUltraSendDgram: adapter not started!\n");
  2932.     status = FAILURE;
  2933.     goto exit;
  2934.     }
  2935.     bzero((char *) &request, sizeof(request));
  2936.     dgramReqPtr = &request.dgram;
  2937.     hdrPtr = &dgramReqPtr->hdr;
  2938.     dgramReqPtr->remoteAddress = wildcardAddress;
  2939.     dgramReqPtr->remoteAddress.tsapSize = 2;
  2940.     dgramReqPtr->remoteAddress.tsap[1] = 1;
  2941.     dgramReqPtr->remoteAddress.address = netAddressPtr->ultra;
  2942.     addressPtr = (Net_Address *) &dgramReqPtr->remoteAddress.address;
  2943.     addressPtr->generic.data[1] = 0x49;
  2944.     addressPtr->generic.data[6] = 0xfe;
  2945.     dgramReqPtr->localAddress = wildcardAddress;
  2946.     dgramReqPtr->localAddress.tsapSize = 2;
  2947.     dgramReqPtr->localAddress.tsap[1] = 1;
  2948.     dgramReqPtr->localAddress.address = 
  2949.     interPtr->netAddress[NET_PROTO_RAW].ultra;
  2950.     addressPtr = (Net_Address *) &dgramReqPtr->localAddress.address;
  2951.     addressPtr->generic.data[1] = 0x49;
  2952.     addressPtr->generic.data[6] = 0xfe;
  2953.     hdrPtr->cmd = NET_ULTRA_DGRAM_SEND_REQ;
  2954.     Timer_GetCurrentTicks(&startTime);
  2955.     while(count > 0) {
  2956.     count--;
  2957.     while(List_IsEmpty(statePtr->freeBufferList)) {
  2958.         int        signal;
  2959.         statePtr->bufferAvail.waiting = TRUE;
  2960.         signal = Sync_SlowMasterWait((unsigned int) &statePtr->bufferAvail,
  2961.             &interPtr->mutex, TRUE);
  2962.         if (signal) {
  2963.         status = GEN_ABORTED_BY_SIGNAL;
  2964.         goto exit;
  2965.         }
  2966.     }
  2967.     itemPtr = List_First(statePtr->freeBufferList);
  2968.     if (itemPtr == statePtr->freeBufferList) {
  2969.         panic("NetUltraSendDgram: list screwup\n");
  2970.     }
  2971.     List_Remove(itemPtr);
  2972.     if (buffer != (Address) NIL) {
  2973.         bcopy((char *) buffer, (char *) itemPtr, bufSize);
  2974.     }
  2975.     dsndCount = count;
  2976. #ifndef CLEAN
  2977.     if (netUltraTrace) {
  2978.         NEXT_TRACE(statePtr, &tracePtr);
  2979.         tracePtr->event = DSND_STREAM;
  2980.         Timer_GetCurrentTicks(&curTime);
  2981.         tracePtr->ticks = curTime;
  2982.     }
  2983. #endif
  2984.     scatter.bufAddr = BUFFER_TO_DVMA(itemPtr, statePtr);
  2985.     scatter.length = bufSize;
  2986.     status = NetUltraSendReq(statePtr, SourceDone, 
  2987.             (ClientData) NIL, FALSE, 1, &scatter,
  2988.             sizeof(NetUltraDatagramRequest), &request);
  2989.     }
  2990.     Timer_GetCurrentTicks(&endTime);
  2991.     Timer_SubtractTicks(endTime, startTime, &endTime);
  2992.     Timer_TicksToTime(endTime, timePtr);
  2993. exit:
  2994.     MASTER_UNLOCK(&interPtr->mutex);
  2995.     return status;
  2996. }
  2997.  
  2998. /*
  2999.  *----------------------------------------------------------------------
  3000.  *
  3001.  * SourceDone --
  3002.  *
  3003.  *    This routine is called by the interrupt handler when a packet
  3004.  *    sent by  NetUltraSource completes.
  3005.  *
  3006.  * Results:
  3007.  *    None.
  3008.  *
  3009.  * Side effects:
  3010.  *    The write buffer associated with the command is added to
  3011.  *     the list of free write buffers.
  3012.  *
  3013.  *----------------------------------------------------------------------
  3014.  */
  3015.  
  3016. static void
  3017. SourceDone(interPtr, infoPtr)
  3018.     Net_Interface    *interPtr;    /* Interface. */
  3019.     NetUltraXRBInfo    *infoPtr;    /* Info about XRB that completed. */
  3020. {
  3021.     NetUltraRequestHdr        *hdrPtr;
  3022.     NetUltraState        *statePtr;
  3023.     List_Links            *itemPtr;
  3024.  
  3025.     hdrPtr = &(infoPtr->xrbPtr->request.dgram.hdr);
  3026.  
  3027.     statePtr = (NetUltraState *) interPtr->interfaceData;
  3028.     if (!(hdrPtr->status & NET_ULTRA_STATUS_OK)) {
  3029.     panic("SourceDone: write failed 0x%x (continuable)\n", hdrPtr->status);
  3030.     } else {
  3031. #ifndef CLEAN
  3032.     if (netUltraDebug) {
  3033.         printf("SourceDone: packet sent\n");
  3034.     }
  3035. #endif
  3036.     statePtr->numWritePending--;
  3037.     if (statePtr->numWritePending < 0) {
  3038.         panic("SourceDone: number of pending writes < 0.\n");
  3039.     }
  3040.     /*
  3041.      * Free up the write buffer. 
  3042.      */
  3043.     itemPtr = (List_Links *) VME_TO_BUFFER(hdrPtr->buffer,statePtr);
  3044.     List_Insert(itemPtr, LIST_ATREAR(statePtr->freeBufferList));
  3045.     if (statePtr->bufferAvail.waiting == TRUE) {
  3046.         Sync_Broadcast(&statePtr->bufferAvail);
  3047.     }
  3048.     }
  3049. }
  3050.  
  3051. /*
  3052.  *----------------------------------------------------------------------
  3053.  *
  3054.  * NetUltraGetStats --
  3055.  *
  3056.  *    Return the statistics for the interface.
  3057.  *
  3058.  * Results:
  3059.  *    A pointer to the statistics structure.
  3060.  *
  3061.  * Side effects:
  3062.  *    None.
  3063.  *
  3064.  *----------------------------------------------------------------------
  3065.  */
  3066.  
  3067. ReturnStatus
  3068. NetUltraGetStats(interPtr, statPtr)
  3069.     Net_Interface    *interPtr;        /* Current interface. */
  3070.     Net_Stats        *statPtr;        /* Statistics to return. */
  3071. {
  3072.     NetUltraState    *statePtr;
  3073.  
  3074.     statePtr = (NetUltraState *) interPtr->interfaceData;
  3075.     MASTER_LOCK(&interPtr->mutex);
  3076.     statPtr->ultra = statePtr->stats;
  3077.     MASTER_UNLOCK(&interPtr->mutex);
  3078.     return SUCCESS;
  3079. }
  3080.  
  3081.